*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "ao.h"
+const __code struct ao_serial_speed ao_serial_speeds[] = {
+ /* [AO_SERIAL_SPEED_4800] = */ {
+ /* .baud = */ 163,
+ /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+ },
+ /* [AO_SERIAL_SPEED_9600] = */ {
+ /* .baud = */ 163,
+ /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+ },
+ /* [AO_SERIAL_SPEED_19200] = */ {
+ /* .baud = */ 163,
+ /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+ },
+ /* [AO_SERIAL_SPEED_57600] = */ {
+ /* .baud = */ 59,
+ /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+ },
+ /* [AO_SERIAL_SPEED_115200] = */ {
+ /* .baud = */ 59,
+ /* .gcr = */ (12 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+ },
+};
+
+#define AO_SERIAL_SPEED_MAX AO_SERIAL_SPEED_115200
+
+#if HAS_SERIAL_1_ALT_1
+#define SERIAL_1_RTS P0_3
+#else
+#define SERIAL_1_RTS P1_5
+#endif
+
+#if HAS_SERIAL_0_ALT_1
+#define SERIAL_0_RTS P0_5
+#else
+#define SERIAL_0_RTS P1_3
+#endif
+
#if HAS_SERIAL_0
volatile __xdata struct ao_fifo ao_serial0_rx_fifo;
#if USE_SERIAL_0_STDIN
ao_wakeup(&ao_stdin_ready);
#endif
+#if HAS_SERIAL_0_HW_FLOW
+ if (ao_fifo_mostly(ao_serial0_rx_fifo))
+ SERIAL_0_RTS = 1;
+#endif
}
static __xdata uint8_t ao_serial0_tx_started;
while (ao_fifo_empty(ao_serial0_rx_fifo))
ao_sleep(&ao_serial0_rx_fifo);
ao_fifo_remove(ao_serial0_rx_fifo, c);
+#if HAS_SERIAL_0_HW_FLOW
+ if (ao_fifo_barely(ao_serial0_rx_fifo))
+ SERIAL_0_RTS = 0;
+#endif
return c;
}
#if USE_SERIAL_0_STDIN
-char
-ao_serial0_pollchar(void) __critical
+int
+_ao_serial0_pollchar(void)
{
- char c;
+ uint8_t c;
if (ao_fifo_empty(ao_serial0_rx_fifo))
return AO_READ_AGAIN;
ao_fifo_remove(ao_serial0_rx_fifo,c);
+#if HAS_SERIAL_0_HW_FLOW
+ if (ao_fifo_barely(ao_serial0_rx_fifo))
+ SERIAL_0_RTS = 0;
+#endif
return c;
}
#endif
ao_serial0_set_speed(uint8_t speed)
{
ao_serial0_drain();
- if (speed > AO_SERIAL_SPEED_57600)
+ if (speed > AO_SERIAL_SPEED_MAX)
return;
U0UCR |= UxUCR_FLUSH;
U0BAUD = ao_serial_speeds[speed].baud;
if (!ao_fifo_full(ao_serial1_rx_fifo))
ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF);
ao_wakeup(&ao_serial1_rx_fifo);
-#if USE_SERIAL1_STDIN
+#if USE_SERIAL_1_STDIN
ao_wakeup(&ao_stdin_ready);
#endif
+#if HAS_SERIAL_1_HW_FLOW
+ if (ao_fifo_mostly(ao_serial1_rx_fifo))
+ SERIAL_1_RTS = 1;
+#endif
}
static __xdata uint8_t ao_serial1_tx_started;
while (ao_fifo_empty(ao_serial1_rx_fifo))
ao_sleep(&ao_serial1_rx_fifo);
ao_fifo_remove(ao_serial1_rx_fifo, c);
+#if HAS_SERIAL_1_HW_FLOW
+ if (ao_fifo_barely(ao_serial1_rx_fifo))
+ SERIAL_1_RTS = 0;
+#endif
return c;
}
#if USE_SERIAL_1_STDIN
-char
-ao_serial1_pollchar(void) __critical
+int
+_ao_serial1_pollchar(void)
{
- char c;
+ uint8_t c;
if (ao_fifo_empty(ao_serial1_rx_fifo))
return AO_READ_AGAIN;
ao_fifo_remove(ao_serial1_rx_fifo,c);
+#if HAS_SERIAL_1_HW_FLOW
+ if (ao_fifo_barely(ao_serial1_rx_fifo))
+ SERIAL_1_RTS = 0;
+#endif
return c;
}
#endif
ao_sleep(&ao_serial1_tx_fifo);
}
-const __code struct ao_serial_speed ao_serial_speeds[] = {
- /* [AO_SERIAL_SPEED_4800] = */ {
- /* .baud = */ 163,
- /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
- },
- /* [AO_SERIAL_SPEED_9600] = */ {
- /* .baud = */ 163,
- /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
- },
- /* [AO_SERIAL_SPEED_19200] = */ {
- /* .baud = */ 163,
- /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
- },
- /* [AO_SERIAL_SPEED_57600] = */ {
- /* .baud = */ 59,
- /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
- },
-};
-
void
ao_serial1_set_speed(uint8_t speed)
{
ao_serial1_drain();
- if (speed > AO_SERIAL_SPEED_57600)
+ if (speed > AO_SERIAL_SPEED_MAX)
return;
U1UCR |= UxUCR_FLUSH;
U1BAUD = ao_serial_speeds[speed].baud;
/* Make the USART pins be controlled by the USART */
P0SEL |= (1 << 2) | (1 << 3);
#if HAS_SERIAL_0_HW_FLOW
- P0SEL |= (1 << 4) | (1 << 5);
+ SERIAL_0_RTS = 0;
+ P0DIR |= (1 << 5);
+
+ P0SEL |= (1 << 4);
+ P0INP |= (1 << 4);
#endif
#else
/* Set up the USART pin assignment */
/* Make the USART pins be controlled by the USART */
P1SEL |= (1 << 5) | (1 << 4);
#if HAS_SERIAL_0_HW_FLOW
- P1SEL |= (1 << 3) | (1 << 2);
+ SERIAL_0_RTS = 0;
+ P1DIR |= (1 << 3);
+
+ P1SEL |= (1 << 2);
+ P1INP |= (1 << 2);
#endif
#endif
IEN0 |= IEN0_URX0IE;
IEN2 |= IEN2_UTX0IE;
#if USE_SERIAL_0_STDIN && !DELAY_SERIAL_0_STDIN
- ao_add_stdio(ao_serial0_pollchar,
+ ao_add_stdio(_ao_serial0_pollchar,
ao_serial0_putchar,
NULL);
#endif
/* Make the USART pins be controlled by the USART */
P0SEL |= (1 << 5) | (1 << 4);
#if HAS_SERIAL_1_HW_FLOW
- P0SEL |= (1 << 3) | (1 << 2);
+ /* SW RTS control (hw doesn't work) */
+ SERIAL_1_RTS = 0;
+ P0DIR |= 1 << 3;
+
+ /* HW CTS. Maybe this works? */
+ P0SEL |= 1 << 2;
+ P0INP |= 1 << 2;
#endif
#else
/* Set up the USART pin assignment */
/* Make the USART pins be controlled by the USART */
P1SEL |= (1 << 6) | (1 << 7);
- P1SEL |= (1 << 5) | (1 << 4);
+#if HAS_SERIAL_1_HW_FLOW
+ /* SW RTS control (hw doesn't work) */
+ SERIAL_1_RTS = 0;
+ P1DIR |= (1 << 5);
+
+ /* HW CTS. Maybe this works? */
+ P1SEL |= (1 << 4);
+ P1INP |= (1 << 4);
+#endif
#endif
/* UART mode with receiver enabled */
IEN2 |= IEN2_UTX1IE;
#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN
- ao_add_stdio(ao_serial1_pollchar,
+ ao_add_stdio(_ao_serial1_pollchar,
ao_serial1_putchar,
NULL);
#endif