+++ /dev/null
-#include "comm.h"
-#include "vend.h"
-
-#define DLAB_SET() bset((void*)&_uart_regs[UART_LINE_CTL], LC_DLAB);
-#define DLAB_CLR() bclr((void*)&_uart_regs[UART_LINE_CTL], LC_DLAB);
-
-char tx_buffer[TX_BUFFER_LEN+2];
-volatile char rx_buffer[RX_BUFFER_LEN+1];
-volatile u8 rx_buf_pos; /* -ve denotes not sending/receiving */
-volatile char msg_buf[RX_BUFFER_LEN+1]; /* rx_buffer copied here without \n */
-volatile u8 rx_queue_state, tx_queue_state;
-volatile bool packet_is_bad;
-
-/* If we were controlling a modem we'd probably do a lot more such as toggling
- * the control lines (DTR,RTS etc). But given this is a very stripped down
- * version talking over merely TX/RX, we don't care about these control lines.
- *
- * This code speak 8 data bits, No parity, 1 Stop bit, at the baud rate specified
- * in comm.h (should be 9600 bps)
- */
-
-u8 uart_init() {
- /*
- * Because in our daughterboard circuit we are not connecting the reset line
- * to the CPU's, we can not make any assumptions about the state of the UART.
- * Hence we initialize all registers and flush the FIFOs
- */
-
- u16 divisor;
- lock(); /* disable interrupts for this */
-
- /* set baud rate */
- divisor = UART_SPEED / BAUD_RATE;
- DLAB_SET();
- _uart_regs[UART_DLAB_MSB] = (u8)(divisor >> 8);
- _uart_regs[UART_DLAB_LSB] = (u8)(divisor & 0xff);
- DLAB_CLR();
-
- /* set RX, TX & LS interrupts */
- _uart_regs[UART_INT_ENABLE] =
- IE_RECEIVER_READY | IE_TRANSMITTER_READY | IE_LINE_STATUS_CHANGE;
-
- /* Enable the FIFO and empty them */
- _uart_regs[UART_FIFO_CTL] =
- FIFO_ENABLE | FIFO_RX_CLEAR | FIFO_TX_CLEAR | FIFO_LVL_1;
-
- /* 8 data bits, 1 stop bit, no parity. */
- _uart_regs[UART_LINE_CTL] = LC_8BITS;
-
- /* modem controls: clear them all */
- _uart_regs[UART_MODEM_CTL] = 0;
-
- rx_queue_state = 0;
- tx_queue_state = 0;
- rx_buf_pos = 0;
-
- unlock();
- return 1;
-}
-
-/*******************************************************************************
- * Interrupt handler for UART.
- *
- * This actually consists of several functions, rolled into one.
- */
-
-extern inline void rx_int() {
- char c = _uart_regs[UART_RX_BUFFER];
- if (rx_queue_state == 2) return; /* buffers full. too bad */
-
- if (rx_buf_pos < RX_BUFFER_LEN) {
- rx_buffer[rx_buf_pos] = c;
-
- if (c == '\n') {
- rx_buf_pos = 0;
- if (packet_is_bad) {
- packet_is_bad = 0;
- /* just forget this packet ever happened */
- } else {
- rx_buffer[rx_buf_pos] = 0;
- switch (rx_queue_state) {
- case 0:
- my_strncpy((char*)msg_buf, (char*)rx_buffer, RX_BUFFER_LEN);
- rx_queue_state++;
- case 1:
- /* we can't copy it in yet. will be done from msg_clr() */
- rx_queue_state++;
- break;
- case 2: /* another weird case? */
- default:
- break;
- }
- }
- } else
- rx_buf_pos++;
- } /* else drop it (buffer full) - probably a corrupt packet */
-}
-
-extern inline void tx_int() {
- /* this interrupt is called with the precondition that the TX fifo of the UART
- * is completely empty and will hold a complete message (of less than 14 chars)
- */
- if (tx_queue_state & 0x01) { /* msg to be sent pending */
- /* load it in */
- int i;
- for (i=0; tx_buffer[i]; i++)
- _uart_regs[UART_TX_BUFFER] = tx_buffer[i];
- bclr((void*)&tx_queue_state, 0x01);
- } else
- bclr((void*)&tx_queue_state, 0x02); /* mark the FIFO as free */
-}
-
-void uart_interrupt() {
- u8 status;
- while (1) {
- status = _uart_regs[UART_INT_IDENT];
- switch (status) {
- case IS_FIFO_TIMEOUT:
- case IS_RECEIVER_READY:
- rx_int();
- break;
- case IS_TRANSMITTER_READY:
- tx_int();
- break;
- case IS_MODEM_STATUS_CHANGE:
- /* read the modem status register to clear the interrupt */
- (void)_uart_regs[UART_MODEM_STATUS];
- break;
- case IS_LINE_STATUS_CHANGE:
- status = _uart_regs[UART_LINE_STATUS];
- if (status & LS_OVERRUN_ERR) packet_is_bad = 1;
- if (status & LS_PARITY_ERR) packet_is_bad = 1;
- if (status & LS_FRAMING_ERR) packet_is_bad = 1;
- /* LS_BREAK_INTERRUPT ignored for now. Do we want it? */
- break;
- default:
- return;
- }
- }
-}
-
-/*******************************************************************************
- * End of interrupt handler
- */
-
-void send_ack() {
- wait_for_tx_free();
- tx_buffer[0] = '!';
- tx_buffer[1] = '\n';
- tx_buffer[2] = 0;
- send_packet();
-}
-
-void send_nack() {
- wait_for_tx_free();
- tx_buffer[0] = '?';
- tx_buffer[1] = '\n';
- tx_buffer[2] = 0;
- send_packet();
-}
-
-/* sends the packet in tx_buffer and doesn't return until it's been sent */
-void send_packet() {
- bset((void*)&tx_queue_state, 0x01);
- lock();
- tx_int();
- unlock();
- while (tx_queue_state & 0x01); /* wait for completion */
-}
-
-void msg_clr() {
- /* called when a msg in msg_buf has been read */
- switch (rx_queue_state) {
- case 0: /* this shouldn't happen */
- break;
- case 1:
- lock();
- rx_queue_state = 0;
- unlock();
- break;
- case 2:
- /* copy the rx_buffer into msg_buf */
- my_strncpy((char*)msg_buf, (char*)rx_buffer, RX_BUFFER_LEN);
- lock();
- rx_queue_state = 1;
- unlock();
- break;
- default:
- lock();
- rx_queue_state = 0;
- unlock();
- }
-}
-
-
-void comm_init() {
- uart_init();
- lock();
- tx_buffer[0] = rx_buffer[0] = msg_buf[0] = 0;
- packet_is_bad = 0;
- unlock();
-}
+++ /dev/null
-#ifndef _COMM_H_
-#define _COMM_H_
-
-#include "vend.h"
-
-/*
- * The communications protocol:
- *
- * \n used for separating packets. Caps is important.
- *
- * Messages Sent:
- * KX - keypad press where X is (ascii 0..9 or R)
- * CYXXXXX - coin balance, XXXXX is number of cents. Y is 0 if we have change,
- * 1 otherwise
- * MXYY - dispense ack/nack. X is what happened (0..MOTOR_*_FAIL), YY is the motor
- * DX - door open/close event where X is 1 for open, 0 for closed.
- * PONG - response to a ping
- *
- * Messages Received:
- * VXX - vend a slot XX
- * DXXXXXXXXXXX - write the string XXXXXXXXXX to screen (10 chars)
- * B - beep
- * U - query current coin balance. - replies with CXXXXX
- * GXXXXX - give change, XXXXX is the amount of the cost of the item hence change
- * is the current value in the coin mech - XXXXX
- * PING - ping. responds with PONG
- *
- */
-
-#define TX_BUFFER_LEN 8 /* maximum 12 due to the way tx_int works with the FIFO */
-extern char tx_buffer[TX_BUFFER_LEN+2]; /* \n + null terminated */
-#define RX_BUFFER_LEN 11
-extern volatile char rx_buffer[RX_BUFFER_LEN+1]; /* null terminated */
-extern volatile char msg_buf[RX_BUFFER_LEN+1]; /* rx_buffer copied here w/o \n */
-
-/* rx_queue_state denotes the state of rx_buffer & msg_buf. Is one of:
- * 0: both rx_buffer & msg_buf are empty and there are no msgs
- * 1: msg_buf has a pending msg, but rx_buffer is not yet full.
- * 2: msg_buf has a pending msg, as does rx_buffer - further msgs will be lost
- */
-extern volatile u8 rx_queue_state;
-
-/* tx_queue_state bits are:
- * bit 0: if the tx_buffer has a message pending to be sent.
- * bit 1: if the TX fifo is in use.
- */
-extern volatile u8 tx_queue_state;
-
-extern inline void wait_for_tx_free() { while (tx_queue_state & 0x01); }
-
-void comm_init();
-void msg_clr();
-void send_packet();
-void send_ack();
-void send_nack();
-
-/*************************************/
-/*** 16550 UART specific #defines ***/
-/*************************************/
-
-#define UART_SPEED 4915200 /* FIXME divide this by some magic number */
-#define BAUD_RATE 9600
-
-/* Register offsets for _uart_regs */
- /* Must be accessed with DLAB low */
-#define UART_RX_BUFFER 0x00 /* read */
-#define UART_TX_BUFFER 0x00 /* write */
-#define UART_INT_ENABLE 0x01
-#define UART_INT_IDENT 0x02 /* read */
-#define UART_FIFO_CTL 0x02 /* write */
-#define UART_LINE_CTL 0x03
-#define UART_MODEM_CTL 0x04
-#define UART_LINE_STATUS 0x05
-#define UART_MODEM_STATUS 0x06
-#define UART_SCRATCH 0x07
-
- /* Same addresses as above, but accessed with DLAB high */
-#define UART_DLAB_LSB 0x00
-#define UART_DLAB_MSB 0x01
-
-extern volatile u8 _uart_regs[]; /* UART registers - fixed at link time */
-
-/* The following #define's adapted from Minix 2.0.0's rs232.c */
-
-/* Interrupt enable bits. */
-#define IE_RECEIVER_READY 1
-#define IE_TRANSMITTER_READY 2
-#define IE_LINE_STATUS_CHANGE 4
-#define IE_MODEM_STATUS_CHANGE 8
-
-/* Interrupt status bits. */
-#define IS_MODEM_STATUS_CHANGE 0x00
-#define IS_TRANSMITTER_READY 0x02
-#define IS_RECEIVER_READY 0x04
-#define IS_LINE_STATUS_CHANGE 0x06
-#define IS_FIFO_TIMEOUT 0x0C
-
-/* FIFO control bits. */
-#define FIFO_ENABLE 0x01
-#define FIFO_RX_CLEAR 0x02
-#define FIFO_TX_CLEAR 0x04
-#define FIFO_DMA_ENABLE 0x08
-#define FIFO_LVL_1 (0x00<<6)
-#define FIFO_LVL_4 (0x01<<6)
-#define FIFO_LVL_8 (0x10<<6)
-#define FIFO_LVL_14 (0x11<<6)
-
-/* Line control bits. */
-#define LC_5BITS 0x00
-#define LC_6BITS 0x01
-#define LC_7BITS 0x10
-#define LC_8BITS 0x11
-#define LC_2STOP_BITS 0x04
-#define LC_PARITY 0x08
-#define LC_PAREVEN 0x10
-#define LC_BREAK 0x40
-#define LC_DLAB 0x80
-
-/* Line status bits. */
-#define LS_DATA_READY 1
-#define LS_OVERRUN_ERR 2
-#define LS_PARITY_ERR 4
-#define LS_FRAMING_ERR 8
-#define LS_BREAK_INTERRUPT 0x10
-#define LS_TRANSMITTER_READY 0x20
-
-/* Modem control bits. */
-#define MC_OUT1 4
-#define MC_OUT2 8
-
-#endif /* _COMM_H_ */