Last active
August 29, 2015 14:22
-
-
Save programmarchy/8e95a3c1c530844eef51 to your computer and use it in GitHub Desktop.
flow control test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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