Compare commits

...

2 commits

Author SHA1 Message Date
Stephan I. Böttcher
33e969b5a2 uart1: fixes, UART1_RX_FLAG_SEND
- major fixes all over
- directly send the received string/data via `printf()`
  even without providing a buffer
  uart1_receive(s=0, 120, UART1_RX_FLAG_SEND)
2024-11-02 13:28:54 +01:00
Stephan I. Böttcher
d11527f131 gpio.h: enumerate CAP and MAT pin functions 2024-11-02 13:26:32 +01:00
3 changed files with 138 additions and 37 deletions

8
gpio.h
View file

@ -23,7 +23,7 @@
* 0.15: (45) AD1.5 Ineg (EINT)
* 0.16: (46) SSP SSEL/MCLK MAT0.2
* 0.17: (47) SSP SCK
* 0.18: (53) SSP MISO
* 0.18: (53) SSP MISO (CAP1.3)
* 0.19: (54) SSP MOSI
* 0.20: (55) SSL SSEL ADC
* 0.21: (1) AD1.6 Vpos (PWM)
@ -33,9 +33,9 @@
* 0.25: (9) AOUT (AD0.4)
* 0.26:
* 0.27:
* 0.28: (13) AD0.1 (MAT)
* 0.29: (14) AD0.2 (MAT)
* 0.30: (15) AD0.3 (MAT, EINT)
* 0.28: (13) AD0.1 (MAT0.2, CAP0.2)
* 0.29: (14) AD0.2 (MAT0.3, CAP0.3)
* 0.30: (15) AD0.3 (CAP0.0, EINT3)
* 0.31: (17) USB UP_LED
*
* 1.16: (16) GPIO OUT (internal pull-up)

6
uart.h
View file

@ -48,10 +48,12 @@ inline static void streol(char *s, int n)
}
enum {
UART1_RX_FLAG_READLINE = 1,
UART1_RX_FLAG_READLINE = 1,
UART1_RX_FLAG_ALL_OR_NOTHING = 2,
UART1_RX_FLAG_FLUSH = 4,
UART1_RX_FLAG_FLUSH = 4,
UART1_RX_FLAG_SEND = 8
};
unsigned int uart1_receive(char *s, unsigned int n, unsigned int flags);
int uart1_send(const char *s, unsigned int n);

159
uart1.c
View file

@ -5,17 +5,20 @@
#include <lpc2148/vic.h>
#include <string.h>
#include "mainloop.h"
#include "message.h"
#include "parser.h"
static char uart1_buffer[128];
#define buffer_size (sizeof(uart1_buffer))
#define buffer(p) uart1_buffer[(p) & (buffer_size - 1)]
#define buffer_mask (buffer_size-1)
#define buffer(p) uart1_buffer[(p) & buffer_mask]
// all access must be with irqs disabled, no volatile
unsigned int tx_read;
unsigned int tx_write;
unsigned int rx_read;
unsigned int rx_write;
static unsigned int tx_read;
static unsigned int tx_write;
static unsigned int rx_read;
static unsigned int rx_write;
// uart1_buffer invariants:
// buffer_size = 2^n
@ -28,20 +31,21 @@ unsigned int rx_write;
inline static
void free_rx_space()
{
if (rx_read + buffer_size == tx_write)
return;
if (rx_read == rx_write) {
rx_read = rx_write = tx_read - buffer_size;
rx_read = rx_write = tx_write - buffer_size;
return;
}
if (tx_read == tx_write) {
tx_read = tx_write = rx_read + buffer_size;
return;
}
if (rx_read == tx_write)
return;
unsigned int nrx_write = tx_write - buffer_size;
rx_read = nrx_write;
unsigned int nrx_read = nrx_write;
while (rx_read != rx_write)
buffer(nrx_write++) = buffer(rx_read++);
rx_read = nrx_read;
rx_write = nrx_write;
}
@ -109,6 +113,29 @@ int uart1_status()
unsigned int uart1_interrupt_count;
unsigned int uart1_overflow;
unsigned int uart1_frame_errors;
unsigned int uart1_mode;
struct uart1_match {
unsigned char size; // available message length
unsigned char val; // eol char
unsigned char max; // max line length to wait for
unsigned char mask; // mask char for eol
} uart1_match = {
.size = 0,
.max = 96,
.mask = 0xff,
.val = '\n',
};
const struct keywords uart1_variable_names[] = {
VARIABLE("uart_mode", &uart1_mode),
VARIABLE("uart_match", &uart1_match),
VARIABLE("uart_irqs", &uart1_interrupt_count),
VARIABLE("uart_overflow", &uart1_overflow),
VARIABLE("uart_errors", &uart1_frame_errors),
VARIABLE("uart_buffer", &uart1_buffer),
KW_END
};
inline static
unsigned int drain_rx_fifo(unsigned int lsr)
@ -127,10 +154,16 @@ unsigned int drain_rx_fifo(unsigned int lsr)
break;
}
}
buffer(rx_write++) = U1RBR;
char d = U1RBR;
buffer(rx_write++) = d;
iir = U1IIR;
lsr = U1LSR;
unsigned int n = rx_write - rx_read;
if ((d & uart1_match.mask) == uart1_match.val
|| n >= uart1_match.max)
uart1_match.size = n;
}
if (!(lsr & UART_LSR_RDR))
U1IER |= UART_IER_RBR;
return lsr;
@ -164,7 +197,8 @@ void uart1_init()
U1LCR = 0;
U1IER = 0;
barrier();
tx_read = tx_write = rx_read = rx_write = 0;
rx_read = rx_write = 0;
tx_read = tx_write = buffer_size;
U1FCR = UART_FCR_Enable | UART_FCR_RxReset | UART_FCR_TxReset | UART_FCR_RxTrigger_14;
U1LCR = UART_LCR_DLAB;
@ -177,6 +211,7 @@ void uart1_init()
baudrate1 = baud_rates[baud1_select].baud;
U1IER |= UART_IER_RBR;
VICVectAddrs[IrqVec_UART1] = uart1_isr;
VICVectCntl[IrqVec_UART1] = VICVectCntl_UART1;
VICIntEnable = VIC_UART1;
@ -185,11 +220,19 @@ void uart1_init()
int uart1_send(const char *s, unsigned int n)
{
unsigned int iflag = disable_irq(IRQ_DISABLE);
if (free_tx_space(n) < n)
return 0;
unsigned int tx_write = tx_write;
memcpy(&buffer(tx_write), s , n);
if (free_tx_space(n) < n) {
n = 0;
goto full;
}
unsigned int nn = buffer_size - (tx_write & buffer_mask);
if (nn >= n)
memcpy(&buffer(tx_write), s, n);
else {
memcpy(&buffer(tx_write), s, nn);
memcpy(&buffer(0), s+nn, n - nn);
}
tx_write += n;
full:
uart1_poll(U1LSR);
enable_irq(iflag);
return n;
@ -199,31 +242,87 @@ unsigned int uart1_receive(char *s, unsigned int n, unsigned int flags)
{
unsigned int iflag = disable_irq(IRQ_DISABLE);
drain_rx_fifo(U1LSR);
unsigned int b = rx_write - rx_read;
enable_irq(iflag);
unsigned int r = 0;
if (rx_write - rx_read < n && flags & UART1_RX_FLAG_ALL_OR_NOTHING)
goto empty;
if (!n)
goto flush;
if (b > n)
b = n;
if (flags & UART1_RX_FLAG_READLINE) {
if (b >= n)
b = n - 1;
unsigned int i;
for (i = rx_read; i < rx_write; i++)
if (buffer(i) == '\n')
for (i = 0; i < b; i++)
if ((buffer(rx_read+i) & uart1_match.mask) == uart1_match.val)
break;
i -= rx_read;
i++;
if (i >= n)
i = n - 1;
n = i;
s[n] = '\0';
if (i == b && i < uart1_match.max && n > uart1_match.max)
b = 0;
else
b = i;
if (s)
s[b] = '\0';
}
unsigned int b = rx_write - rx_read;
if (n)
memcpy(s, &buffer(rx_read), n);
rx_read += n;
else if (b < n && flags & UART1_RX_FLAG_ALL_OR_NOTHING)
goto empty;
if (!b)
goto empty;
unsigned int bb = buffer_size - (rx_read & buffer_mask);
if (s)
if (bb >= b)
memcpy(s, &buffer(rx_read), b);
else {
memcpy(s, &buffer(rx_read), bb);
memcpy(s + bb, &buffer(0), b - bb);
}
if (flags & UART1_RX_FLAG_SEND)
if (flags & UART1_RX_FLAG_READLINE) {
if (s)
printf("UT %s←UT\n", s);
else if (bb >= b)
printf("UT %.*s←UT\n", b, &buffer(rx_read));
else
printf("UT %.*s%.*s←UT\n",
bb, &buffer(rx_read),
b - bb, &buffer(rx_read + bb) );
}
else {
printf("UX");
for (unsigned int i=0; i < b; i++)
printf(" %02x", buffer(rx_read+i));
printf("\n");
}
rx_read += b;
r = b;
flush:
if (flags & UART1_RX_FLAG_FLUSH)
if (flags & UART1_RX_FLAG_FLUSH) {
rx_read = rx_write;
uart1_match.size = 0;
}
empty:
U1IER |= UART_IER_RBR;
iflag = disable_irq(IRQ_DISABLE);
b = rx_write - rx_read;
if (b >= uart1_match.max)
uart1_match.size = b;
else {
uart1_match.size = 0;
for (unsigned int i=0; i<b; i++)
if ((buffer(rx_read+i) & uart1_match.mask) == uart1_match.val) {
uart1_match.size = i;
break;
}
}
enable_irq(iflag);
return r;
}