ASCII Serial Com
Serial communication library between computers, microcontrollers, FPGAs, etc. Uses only ASCII. Not the most efficient protocol, but meant to be easy to read
Loading...
Searching...
No Matches
arduino_uno_asc_loopback.c
1#include "asc_exception.h"
2#include "asc_helpers.h"
3#include "ascii_serial_com.h"
4#include "avr/avr_timers.h"
5#include "avr/avr_uart.h"
6#include "circular_buffer.h"
7
8#include <avr/interrupt.h>
9#include <stdio.h>
10#include <util/atomic.h>
11
12#define F_CPU 16000000L
13#define BAUD 9600
14#define MYUBRR (F_CPU / 16 / BAUD - 1)
15#define UART_NO 0
16
17// period = 1024*256*n_overflows / F_CPU
18#define n_overflows F_CPU / 1024 / 256 / 2
19
20#define NCHARINLINE 16
21
22char dataBuffer[MAXDATALEN];
24
25#define extraInputBuffer_size 64
26uint8_t extraInputBuffer_raw[extraInputBuffer_size];
27circular_buffer_uint8 extraInputBuffer;
28circular_buffer_uint8 *asc_in_buf;
29circular_buffer_uint8 *asc_out_buf;
30
31CEXCEPTION_T e;
32char ascVersion, appVersion, command;
33size_t dataLen;
34
35uint16_t nExceptions;
36
37static int uart_putchar(char c, FILE *stream);
38
39static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
40
41#pragma GCC diagnostic ignored "-Wunused-variable"
42#pragma GCC diagnostic push
43#pragma GCC diagnostic ignored "-Wunused-parameter"
44#pragma GCC diagnostic push
45static int uart_putchar(char c, FILE *stream) {
46 uart_tx(0, c);
47 return 0;
48}
49#pragma GCC diagnostic pop
50#pragma GCC diagnostic pop
51
52static void print_buffer(const char *title, const circular_buffer_uint8 *cb);
53static void print_buffer(const char *title, const circular_buffer_uint8 *cb) {
54 printf("%s\n", title);
55 const unsigned sz = circular_buffer_get_size_uint8(cb);
56 printf(" size: %u\n ", sz);
57 for (size_t i = 0; i < sz; i++) {
58 char el = circular_buffer_get_element_uint8(cb, i);
59 if (el == '\n') {
60 printf("\\n");
61 } else {
62 printf("%c", el);
63 }
64 }
65 printf("\n ");
66 for (size_t i = 0; i < cb->capacity; i++) {
67 char el = cb->buffer[i];
68 if (el == '\n') {
69 printf("\\n");
70 } else {
71 printf("%c", el);
72 }
73 }
74 printf("\n ");
75 if (cb->iStart == cb->iStop) {
76 for (size_t i = 0; i < cb->capacity; i++) {
77 if (i == cb->iStart) {
78 printf("X");
79 } else {
80 printf(" ");
81 }
82 }
83 } else {
84 for (size_t i = 0; i < cb->capacity; i++) {
85 if (i == cb->iStart) {
86 printf(">");
87 } else if (i == cb->iStop) {
88 printf("<");
89 } else {
90 printf(" ");
91 }
92 }
93 }
94 printf("\n");
95}
96
97// static void print_memory(const char *title, void *address, size_t nBytes);
98// static void print_memory(const char *title, void *address, size_t nBytes) {
99// const size_t nLines = nBytes / NCHARINLINE;
100// printf("%s\n", title);
101// for (size_t iLine = 0; iLine < nLines; iLine++) {
102// printf("%p ", address + iLine * NCHARINLINE);
103// size_t nCharThisLine = NCHARINLINE;
104// if (iLine == nLines - 1)
105// nCharThisLine = nBytes % NCHARINLINE;
106// for (size_t iChar = 0; iChar < nCharThisLine; iChar++) {
107// printf("%02hhX", *((uint8_t *)(address + iLine * NCHARINLINE +
108// iChar)));
109// }
110// printf("\n");
111// }
112// }
113
114int main(void) {
115
116 nExceptions = 0;
117 stdout = &mystdout;
118
119 Try {
121 ascii_serial_com_set_ignore_CRC_mismatch(&asc);
122 asc_in_buf = ascii_serial_com_get_input_buffer(&asc);
123 asc_out_buf = ascii_serial_com_get_output_buffer(&asc);
124
125 circular_buffer_init_uint8(&extraInputBuffer, extraInputBuffer_size,
126 extraInputBuffer_raw);
127 }
128 Catch(e) { return e; }
129
130 UART_Init(UART_NO, MYUBRR, 1);
131
132 TIMER0_Init(5, 0, 1);
133 DDRB |= _BV(5);
134
135 sei();
136
137 // printf("####\n");
138 // printf("asc loc: %p\n", &asc);
139 // printf("asc_in_buf loc: %p\n", asc_in_buf);
140 // printf("asc_out_buf loc: %p\n", asc_out_buf);
141 // printf("asc->raw_buffer loc: %p\n", &asc.raw_buffer);
142 // printf("asc->ignoreCRCMismatch loc: %p\n", &asc.ignoreCRCMismatch);
143 // printf("asc_in_buf->buffer loc: %p\n", asc_in_buf->buffer);
144 // printf("asc_out_buf->buffer loc: %p\n", asc_out_buf->buffer);
145 // printf("####\n");
146 // print_memory("ASC:", &asc, 256);
147 // printf("####\n");
148 // print_memory("asc.raw_buffer", asc.raw_buffer, 128);
149 // printf("####\n");
150 // print_memory("asc_in_buf.buffer", asc_in_buf->buffer, 64);
151 // printf("####\n");
152 // print_memory("asc_out_buf.buffer", asc_out_buf->buffer, 64);
153 // printf("####\n");
154
155 while (true) {
156 Try {
157
158 // if (USART0_can_read_Rx_data) {
159 // uint8_t byte = UDR0;
160 // if (byte == 0x3F) { // '?'
161 // print_buffer("in", asc_in_buf);
162 // print_buffer("out", asc_out_buf);
163 // } else {
164 // circular_buffer_push_back_uint8(asc_in_buf, byte);
165 // }
166 //}
167
168 if (!circular_buffer_is_empty_uint8(&extraInputBuffer)) {
169 uint8_t byte;
170 ATOMIC_BLOCK(ATOMIC_FORCEON) {
171 byte = circular_buffer_pop_front_uint8(&extraInputBuffer);
172 }
173 if (byte == 0x3F) { // '?'
174 print_buffer("in", asc_in_buf);
175 print_buffer("out", asc_out_buf);
176 } else {
177 circular_buffer_push_back_uint8(asc_in_buf, byte);
178 }
179 }
180
181 if (!circular_buffer_is_empty_uint8(asc_in_buf)) {
183 &asc, &ascVersion, &appVersion, &command, dataBuffer, &dataLen);
184 if (command != '\0') {
185 // printf("Got a message!:\n");
186 // print_buffer("in", asc_in_buf);
188 &asc, ascVersion, appVersion, command, dataBuffer, dataLen);
189 // print_buffer("out", asc_out_buf);
190 }
191 }
192
193 uart_tx_from_circ_buf(UART_NO, asc_out_buf);
194 }
195 Catch(e) { nExceptions++; }
196 }
197
198 return 0;
199}
200
201ISR(USART_RX_vect) { uart_rx_to_circ_buf(UART_NO, &extraInputBuffer); }
202
203ISR(TIMER0_OVF_vect) {
204 static uint16_t timer_overflow_count;
205 timer_overflow_count += 1;
206 if (timer_overflow_count == n_overflows) {
207 PORTB ^= _BV(5); // flip bit
208 timer_overflow_count = 0;
209 }
210}
#define uart_tx(uart_no, data)
#define uart_rx_to_circ_buf(uart_no, circ_buf_ptr)
Receive a byte from UART into circular buffer.
#define uart_tx_from_circ_buf(uart_no, circ_buf_ptr)
Transmit a byte from the circular buffer.
circular_buffer_uint8 * ascii_serial_com_get_output_buffer(ascii_serial_com *asc)
ASCII Serial Com get output buffer.
void ascii_serial_com_init(ascii_serial_com *asc)
ASCII Serial Com Interface init method.
void ascii_serial_com_put_message_in_output_buffer(ascii_serial_com *asc, char ascVersion, char appVersion, char command, const char *data, size_t dataLen)
ASCII Serial Com Pack and put message in output buffer.
void ascii_serial_com_get_message_from_input_buffer(ascii_serial_com *asc, char *ascVersion, char *appVersion, char *command, char *data, size_t *dataLen)
ASCII Serial Com pop message from input buffer and unpack.
circular_buffer_uint8 * ascii_serial_com_get_input_buffer(ascii_serial_com *asc)
ASCII Serial Com get input buffer.
#define TIMER0_Init(cs, ctc, timsk0)
Initialize Timer0.
Definition avr_timers.h:28
#define UART_Init(uart_no, ubrr, rxIntEnable)
Initialize USART.
Definition avr_uart.h:20
size_t circular_buffer_get_size_uint8(const circular_buffer_uint8 *circ_buf)
circular buffer get number of elements
void circular_buffer_init_uint8(circular_buffer_uint8 *circ_buf, const size_t capacity, uint8_t *buffer)
circular buffer init method
uint8_t circular_buffer_get_element_uint8(const circular_buffer_uint8 *circ_buf, const size_t iElement)
circular buffer get element
uint8_t circular_buffer_pop_front_uint8(circular_buffer_uint8 *circ_buf)
circular buffer pop front
bool circular_buffer_is_empty_uint8(const circular_buffer_uint8 *circ_buf)
circular buffer get if empty
void circular_buffer_push_back_uint8(circular_buffer_uint8 *circ_buf, const uint8_t element)
circular buffer push back
ASCII Serial Com Interface State struct.
circular buffer struct