Skip to content

Instantly share code, notes, and snippets.

@programmarchy
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save programmarchy/8e95a3c1c530844eef51 to your computer and use it in GitHub Desktop.
Save programmarchy/8e95a3c1c530844eef51 to your computer and use it in GitHub Desktop.
flow control test
#include <asf.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <stdint.h>
#define PIN_SET_OUTPUT(ddr, id) ddr |= _BV(id)
#define PIN_SET_INPUT(ddr, id) ddr &= ~_BV(id)
#define PIN_SET_HIGH(port, id) port |= _BV(id)
#define PIN_SET_LOW(port, id) port &= ~_BV(id)
#define PIN_IS_HIGH(pins, id) bit_is_set(pins, id)
#define PIN_IS_LOW(pins, id) bit_is_clear(pins, id)
#define BLUETOOTH_STREAM_LENGTH 128
#define BLUETOOTH_STREAM_HIGH_WATER_MARK 64
typedef struct
{
uint8_t data[BLUETOOTH_STREAM_LENGTH];
uint8_t index;
} buffer_t;
uint8_t buffer_pop_unsafe(buffer_t *);
void buffer_push_unsafe(buffer_t *, uint8_t);
uint8_t buffer_is_empty(buffer_t *);
uint8_t buffer_is_full(buffer_t *);
buffer_t bluetooth_read_buffer;
buffer_t bluetooth_write_buffer;
void bluetooth_init (void);
uint8_t bluetooth_is_connected (void);
uint8_t bluetooth_read (uint8_t);
uint8_t bluetooth_write (uint8_t);
void bluetooth_pipe (void);
void bluetooth_clear_to_send (uint8_t);
uint8_t bluetooth_is_ready_to_send (void);
void leds_init (void);
void leds_blue_on (void);
void leds_blue_off (void);
void leds_green_on (void);
void leds_green_off (void);
void leds_red_on (void);
void leds_red_off (void);
void spin_loop (uint32_t);
void spin_trap (void);
void loop (void);
void transform (void);
int main (void)
{
board_init();
bluetooth_init();
leds_init();
// Insert application code here, after the board has been initialized.
wdt_enable(WDTO_8S);
wdt_reset();
while (1)
{
if (bit_is_set(UCSR1A, DOR1))
{
leds_red_on();
leds_green_on();
leds_blue_on();
spin_trap();
}
loop();
}
return 0;
}
void loop (void)
{
wdt_reset();
if (bluetooth_is_connected())
{
leds_blue_on();
bluetooth_pipe();
transform();
}
else
{
leds_blue_off();
}
}
void transform (void)
{
while (!buffer_is_empty(&bluetooth_read_buffer) && !buffer_is_full(&bluetooth_write_buffer))
{
buffer_push_unsafe(&bluetooth_write_buffer,
buffer_pop_unsafe(&bluetooth_read_buffer));
}
}
void spin_trap (void)
{
while (1)
{
wdt_reset();
asm("nop");
}
}
void spin_loop (uint32_t ticks)
{
for (uint32_t i = 0; i < ticks; ++i)
{
wdt_reset();
asm("nop");
}
}
uint8_t buffer_pop_unsafe(buffer_t *buf)
{
return buf->data[--buf->index];
}
void buffer_push_unsafe(buffer_t *buf, uint8_t byte_to_push)
{
buf->data[buf->index++] = byte_to_push;
}
uint8_t buffer_is_empty(buffer_t *buf)
{
return buf->index == 0;
}
uint8_t buffer_is_full(buffer_t *buf)
{
return buf->index == BLUETOOTH_STREAM_LENGTH;
}
void bluetooth_init (void)
{
// UART
UBRR1L = 25; // set baud rate to 38.4k
UCSR1A |= (1 << U2X1); // turn off double speed
UCSR1A |= (1 << TXC1); // clear any existing transmits
UCSR1B |= (1 << TXEN1) | (1 << RXEN1); // enable transmitter and receiver
UCSR1C = (1 << UMSEL11) | (1 << UCSZ11) | (1 << UCSZ10); // 8 data bits, 1 stop bit
// Reset pin
PIN_SET_OUTPUT(DDRC, 7);
PIN_SET_HIGH(PORTC, 7);
// RTS
PIN_SET_INPUT(DDRA, 2);
PIN_SET_LOW(PORTA, 2);
// CTS
PIN_SET_OUTPUT(DDRB, 1);
PIN_SET_LOW(PORTB, 1);
// Connection status pin
PIN_SET_INPUT(DDRC, 5);
PIN_SET_LOW(PORTC, 5);
}
void bluetooth_clear_to_send (uint8_t cts)
{
if (cts)
{
PIN_SET_LOW(PORTB, 1);
}
else
{
PIN_SET_HIGH(PORTB, 1);
}
}
uint8_t bluetooth_is_ready_to_send (void)
{
if (PIN_IS_LOW(PINA, 2))
{
return 1;
}
else
{
return 0;
}
}
uint8_t bluetooth_read (uint8_t n)
{
uint8_t count = 0;
while (bit_is_set(UCSR1A, RXC1) && !buffer_is_full(&bluetooth_read_buffer) && count++ < n)
{
// read a byte
buffer_push_unsafe(&bluetooth_read_buffer, UDR1);
wdt_reset();
}
return count;
}
uint8_t bluetooth_write (uint8_t n)
{
uint8_t count = 0;
// wait until transmit buffer is empty
while (bit_is_clear(UCSR1A, UDRE1))
{
wdt_reset();
}
while (!buffer_is_empty(&bluetooth_write_buffer) && bluetooth_is_ready_to_send() && count++ < n)
{
// write a byte
UDR1 = buffer_pop_unsafe(&bluetooth_write_buffer);
// wait until transmit buffer is empty
while (bit_is_clear(UCSR1A, UDRE1))
{
wdt_reset();
}
// wait until entire frame in transmit shift register has been shifted out
while (bit_is_clear(UCSR1A, TXC1))
{
wdt_reset();
}
// clear transmit complete flag
UCSR1A |= (1 << TXC1);
}
return count;
}
void bluetooth_pipe (void)
{
// read up until high water mark
bluetooth_clear_to_send(1);
uint8_t read_index = bluetooth_read_buffer.index;
uint8_t read_max = (read_index >= BLUETOOTH_STREAM_HIGH_WATER_MARK) ? 0 : BLUETOOTH_STREAM_HIGH_WATER_MARK - read_index;
bluetooth_read(read_max);
bluetooth_clear_to_send(0);
// write as many bytes as possible
uint8_t write_index = bluetooth_write_buffer.index;
uint8_t write_max = BLUETOOTH_STREAM_LENGTH - write_index;
uint8_t write_actual = bluetooth_write(write_max);
if (write_actual < write_max && write_index > 0)
{
// read past the high water mark if not all bytes were read
bluetooth_clear_to_send(1);
bluetooth_read(BLUETOOTH_STREAM_LENGTH);
bluetooth_clear_to_send(0);
}
}
uint8_t bluetooth_is_connected (void)
{
return PIN_IS_HIGH(PINC, 5);
}
void leds_init (void)
{
// Blue LED
PIN_SET_OUTPUT(DDRC, 2);
PIN_SET_HIGH(PORTC, 2);
// Green LED
PIN_SET_OUTPUT(DDRA, 0);
PIN_SET_HIGH(PORTA, 0);
// Red LED
PIN_SET_OUTPUT(DDRA, 7);
PIN_SET_HIGH(PORTA, 7);
}
void leds_blue_on (void)
{
PIN_SET_LOW(PORTC, 2);
}
void leds_blue_off (void)
{
PIN_SET_HIGH(PORTC, 2);
}
void leds_green_on (void)
{
PIN_SET_LOW(PORTA, 0);
}
void leds_green_off (void)
{
PIN_SET_HIGH(PORTA, 0);
}
void leds_red_on (void)
{
PIN_SET_LOW(PORTA, 7);
}
void leds_red_off (void)
{
PIN_SET_HIGH(PORTA, 7);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment