qmsk.dmx.control: switch to readline() based __iter__, with __call__(poll=True) and **opts
/** Serial modes */
static enum {
SERIAL_MODE_ASYNC = 0b00,
} serial_mode = SERIAL_MODE_ASYNC;
static enum {
SERIAL_BAUD_9600 = 103,
} serial_baud = SERIAL_BAUD_9600;
static enum {
SERIAL_PARITY_N = 0b00,
} serial_parity = SERIAL_PARITY_N;
static enum {
SERIAL_STOPBITS_1 = 0b0,
} serial_stopbits = SERIAL_STOPBITS_1;
static enum {
SERIAL_CHARS_8 = 0b011,
} serial_chars = SERIAL_CHARS_8;
/** Serial state */
#define SERIAL_BUF 64
struct serial {
char buf[SERIAL_BUF];
byte in, out;
} serial_rx;
char serial_tx = 0;
void serial_enable (char rx, char tx);
/*
* Setup the UART for serial mode.
*/
void serial_init ()
{
UCSR0A = (
// Double the USART Transmission Speed
(0b0 << U2X0) // single speed
// Multi-processor Communication Mode
| (0b0 << MPCM0) // off
);
UCSR0B = (
// Character Size
((serial_chars >> 2) << UCSZ02) // standard character sizes
);
UCSR0C = (
// USART Mode Select
(serial_mode << UMSEL00) // async
// Parity Mode
| (serial_parity << UPM00)
// Stop Bit Select
| (serial_stopbits << USBS0)
// Character Size
| ((serial_chars & 0b11) << UCSZ00)
// Clock Polarity
| (0b0 << UCPOL0)
);
UBRR0 = serial_baud;
// active RX, idle TX
serial_enable(1, 0);
}
void serial_enable (char rx, char tx)
{
UCSR0B = (
// RX Complete Interrupt Enable
(!!rx << RXCIE0)
// USART Data Register Empty Interrupt Enable
| (!!tx << UDRIE0)
// Receiver Enable
| (0b1 << RXEN0) // enabled
// Transmitter Enable
| (0b1 << TXEN0) // enabled
// Character Size
| ((serial_chars >> 2) << UCSZ02) // standard character sizes
);
}
/*
* Read incoming into buffer.
*/
ISR(USART_RX_vect)
{
serial_rx.buf[serial_rx.in++] = UDR0;
if (serial_rx.in >= SERIAL_BUF)
serial_rx.in = 0;
}
/*
* Write outgoing buffer.
*/
ISR(USART_UDRE_vect)
{
UDR0 = serial_tx;
// tx buffer consumed
serial_tx = 0;
// idle tx
serial_enable(1, 0);
}
char serial_read ()
{
if (serial_rx.out == serial_rx.in)
return 0;
char rx = serial_rx.buf[serial_rx.out++];
if (serial_rx.out >= SERIAL_BUF)
serial_rx.out = 0;
return rx;
}
void serial_write (char c)
{
// XXX: atomic?
if (tbi(&UCSR0A, UDRE0)) {
// direct
UDR0 = c;
} else {
// buffered
serial_tx = c;
serial_enable(1, 1);
}
}