vfdboard/firmware/uart.c

249 lines
5.7 KiB
C
Executable File

/* Name: uart.c
* Project: AVR USB driver for CDC interface on Low-Speed USB
* Author: Osamu Tamura
* Creation Date: 2006-06-18
* Tabsize: 4
* Copyright: (c) 2006 by Recursion Co., Ltd.
* License: Proprietary, free under certain conditions. See Documentation.
*
* 2006-07-08 adapted to higher baudrate by T.Kitazawa
*/
/*
General Description:
This module implements the UART rx/tx system of the USB-CDC driver.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h> /* needed by usbdrv.h */
#include "oddebug.h"
#include "usbdrv.h"
#include "uart.h"
#include "hcs12ss59t/hcs12ss59t.h"
#include <stdlib.h>
#include <avr/wdt.h>
#define TX(data) {rx_buf[rx_write_ptr] = data; rx_write_ptr = (rx_write_ptr+1) & RX_MASK;}
extern uchar sendEmptyFrame;
/* UART buffer */
uchar rx_read_ptr, tx_write_ptr, tx_read_ptr, rx_write_ptr;
uchar rx_buf[RX_SIZE+HW_CDC_BULK_IN_SIZE], tx_buf[TX_SIZE];
uchar byte_counter = 0;
uchar cmd = 0;
#define BUFSZ 12
char dbuf[BUFSZ];
uchar cmax = 0;
void uartInit(ulong baudrate, uchar parity, uchar stopbits, uchar databits)
{
usbDWord_t br;
br.dword = ((F_CPU>>3)+(baudrate>>1)) / baudrate - 1;
UCSR0A |= (1<<U2X0);
#if DEBUG_LEVEL < 1
/* USART configuration */
UCSR0B = 0;
UCSR0C = URSEL_MASK | ((parity==1? 3:parity)<<UPM00) | ((stopbits>>1)<<USBS0) | ((databits-5)<<UCSZ00);
UBRR0L = br.bytes[0];
UBRR0H = br.bytes[1];
#else
DBG1(0xf0, br.bytes, 2);
#endif /* DEBUG_LEVEL */
}
void txs(char *string)
{
while (*string) {
TX(*string);
string++;
}
}
void uartPoll(void)
{
uchar next;
uchar data;
uchar temp;
int echo = 0;
int ok = 1;
while(tx_write_ptr!=tx_read_ptr) {
data = tx_buf[tx_read_ptr];
if (cmax && (byte_counter >= cmax)) {
data = 0;
cmax = 0;
}
if ((!cmax) && ((data < 32) || (data > 127))) { // any control character - cmd done
if (cmd) {
txs("\r\n");
switch (cmd) {
case 't':
hcs12ss59t_set_text(dbuf);
break;
case 'T':
hcs12ss59t_set_buffer(dbuf);
break;
case 'b':
temp = atol(dbuf);
if (temp < 16) {
hcs12ss59t_set_brightness(temp);
} else {
ok = 0;
}
break;
case 'B':
temp = dbuf[0];
if (temp < 16) {
hcs12ss59t_set_brightness(temp);
} else {
ok = 0;
}
break;
case 'p':
if (dbuf[0] == '1') {
FILAMENT_EN;
hcs12ss59t_set_lights(HCS12SS59T_LINORM);
} else if (dbuf[0] == '0') {
FILAMENT_DIS;
hcs12ss59t_set_lights(HCS12SS59T_LIOFF);
} else if (dbuf[0] == 't') {
FILAMENT_EN;
hcs12ss59t_set_lights(HCS12SS59T_LION);
} else {
ok = 0;
}
break;
case 'r':
hcs12ss59t_set_text(" ");
hcs12ss59t_reset();
break;
case 'R':
cli();
hcs12ss59t_set_text(" ");
wdt_enable(WDTO_15MS);
while (1); // WD Timeout -> CPU reset
break;
case 'C':
hcs12ss59t_set_character(dbuf[0], dbuf+1, 1);
break;
case 'h':
case '?':
txs("text : t<12b ASCII>\r\n");
txs(" : T<12b RAW>\r\n");
txs("power : p<0/1>\r\n");
txs("brgn : b<0 - 15>\r\n");
txs("shift : s<ASCII>...\r\n");
txs(" : S<RAW>...\r\n");
//txs("reset : r / R\r\n");
//txs("cgram : C<adr><2b RAW>\r\n");
//txs("p-bar : xx enable progressbar\r\n");
//txs(" : x<00-60> <00-60>\r\n");
//txs(" : X<2b RAW>\r\n");
break;
case 'x':
if (dbuf[0] == 'x') {
hcs12ss59t_set_progress(0, 0);
hcs12ss59t_en_progress();
} else {
hcs12ss59t_set_progress(atol(dbuf),
atol(dbuf + 3));
}
break;
case 'X':
hcs12ss59t_set_progress(dbuf[0], dbuf[1]);
break;
default:
ok = 0;
break;
}
if (ok)
txs("OK.");
else
txs("ERR");
cmd = 0;
byte_counter = 0;
}
txs("\r\n>");
} else { // ASCII character
if (cmd == 0) {
echo = 1;
cmd = data;
for (int i = 0; i < BUFSZ; ++i) {
dbuf[i] = 0;
}
switch (cmd) {
case 'T':
cmax = BUFSZ;
break;
case 'B':
cmax = 1;
break;
case 'C':
cmax = 3;
break;
default:
cmax = 0;
break;
}
} else {
if (cmd == 's' || cmd == 'S') { // Shift mode
for (int i = 1; i < HCS12SS59T_NUMDIGITS; ++i) {
dbuf[i - 1] = dbuf[i];
}
dbuf[HCS12SS59T_NUMDIGITS - 1] = data;
if (cmd == 's')
hcs12ss59t_set_text(dbuf);
else
hcs12ss59t_set_buffer(dbuf);
echo = 1;
}
else if (byte_counter < BUFSZ) {
echo = 1;
dbuf[byte_counter] = data;
byte_counter++;
}
}
}
if (echo)
TX(data); // Echo
tx_read_ptr = (tx_read_ptr+1) & TX_MASK;
if( usbAllRequestsAreDisabled() && uartTxBytesFree()>HW_CDC_BULK_OUT_SIZE ) {
usbEnableAllRequests();
}
}
/* USB <= device */
if( usbInterruptIsReady() && (rx_write_ptr!=rx_read_ptr || sendEmptyFrame) ) {
uchar bytesRead, i;
bytesRead = (rx_write_ptr-rx_read_ptr) & RX_MASK;
if(bytesRead>HW_CDC_BULK_IN_SIZE)
bytesRead = HW_CDC_BULK_IN_SIZE;
next = rx_read_ptr + bytesRead;
if( next>=RX_SIZE ) {
next &= RX_MASK;
for( i=0; i<next; i++ )
rx_buf[RX_SIZE+i] = rx_buf[i];
}
usbSetInterrupt(rx_buf+rx_read_ptr, bytesRead);
rx_read_ptr = next;
if( bytesRead ) {
// UART_CTRL_PORT |= (1<<UART_CTRL_RTS);
}
/* send an empty block after last data block to indicate transfer end */
sendEmptyFrame = (bytesRead==HW_CDC_BULK_IN_SIZE && rx_write_ptr==rx_read_ptr)? 1:0;
}
}