| 1 |
4 |
atypic |
#include <avr/io.h>
|
| 2 |
|
|
#include <avr/interrupt.h>
|
| 3 |
|
|
#include <stdint.h>
|
| 4 |
|
|
#include <global.h>
|
| 5 |
|
|
#include <device.h>
|
| 6 |
|
|
#include <dispatch.h>
|
| 7 |
|
|
#include <stdlib.h>
|
| 8 |
|
|
#include <string.h>
|
| 9 |
|
|
|
| 10 |
|
|
#define BAUD 9600
|
| 11 |
|
|
#define MUBRR ((FOSC/16/BAUD)-1)
|
| 12 |
|
|
|
| 13 |
|
|
|
| 14 |
|
|
static struct {
|
| 15 |
|
|
struct buf readbuf;
|
| 16 |
|
|
struct buf writebuf;
|
| 17 |
|
|
} kvga_data;
|
| 18 |
|
|
|
| 19 |
|
|
/* Commands to KVGA. */
|
| 20 |
|
|
#define ECHO_ON "\033[12h"
|
| 21 |
|
|
#define ECHO_OFF "\033[12l"
|
| 22 |
|
|
|
| 23 |
|
|
/* Newline, linefeed, carriage return commands. */
|
| 24 |
|
|
#define SET_NEWLINE_MODE "\033[20h"
|
| 25 |
|
|
#define SET_LINEFEED_MODE "\033[20l"
|
| 26 |
|
|
#define ENABLE_AUTO_LF "\033[>8h"
|
| 27 |
|
|
#define DISABLE_AUTO_LF "\033[>8l"
|
| 28 |
|
|
#define ENABLE_AUTO_CR "\033[>9h"
|
| 29 |
|
|
#define DISABLE_AUTO_CR "\033[>9l"
|
| 30 |
|
|
|
| 31 |
|
|
/* Status line commands. */
|
| 32 |
|
|
#define ENABLE_STATUSLINE "\033[?15l"
|
| 33 |
|
|
#define DISABLE_STATUSLINE "\033[?15h"
|
| 34 |
|
|
|
| 35 |
|
|
|
| 36 |
|
|
static igordev_read_fn_t kvga_recv;
|
| 37 |
|
|
static igordev_write_fn_t kvga_send;
|
| 38 |
|
|
static igordev_init_fn_t kvga_init;
|
| 39 |
|
|
static igordev_flush_fn_t kvga_flush;
|
| 40 |
|
|
|
| 41 |
|
|
struct igordev igordev_kvga = {
|
| 42 |
|
|
.init = kvga_init,
|
| 43 |
|
|
.read = kvga_recv,
|
| 44 |
|
|
.write = kvga_send,
|
| 45 |
|
|
.flush = kvga_flush,
|
| 46 |
|
|
.read_status = 0,
|
| 47 |
|
|
.write_status = 0,
|
| 48 |
|
|
.priv = &kvga_data
|
| 49 |
|
|
};
|
| 50 |
|
|
|
| 51 |
|
|
|
| 52 |
|
|
void
|
| 53 |
|
|
kvga_init(void)
|
| 54 |
|
|
{
|
| 55 |
|
|
const char *hello = "Hello, world from TVT-KVGA!\r\n";
|
| 56 |
|
|
// const char *dummyprompt = "igor> ";
|
| 57 |
|
|
|
| 58 |
|
|
/* Set internal stuff first. */
|
| 59 |
|
|
buf_init(&kvga_data.readbuf);
|
| 60 |
|
|
buf_init(&kvga_data.writebuf);
|
| 61 |
|
|
igordev_kvga.read_status = igordev_kvga.write_status = IDEV_STATUS_OK;
|
| 62 |
|
|
|
| 63 |
|
|
// Set identification register.
|
| 64 |
|
|
igordev_kvga.id = (CAN_READ | CAN_WRITE |
|
| 65 |
|
|
(DEVTYPE_TERM << DEVTYPE_OFFSET));
|
| 66 |
|
|
|
| 67 |
|
|
// Disable powersaving
|
| 68 |
|
|
PRR1 &= ~(1<<PRUSART1);
|
| 69 |
|
|
|
| 70 |
|
|
// Set tranfser speed
|
| 71 |
|
|
UBRR1L = (uint8_t)MUBRR;
|
| 72 |
|
|
UBRR1H = (uint8_t)(MUBRR>>8);
|
| 73 |
|
|
|
| 74 |
|
|
// Enable reciever, transmitter and interrupts ( Not active until global interrupts are enabled)
|
| 75 |
|
|
UCSR1B = (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);
|
| 76 |
|
|
|
| 77 |
|
|
// Set format, stopbits, mode: 8n1
|
| 78 |
|
|
UCSR1C = (0<<USBS1)|(0<<UPM11)|(0<<UPM10)|(0<<UMSEL11)|(0<<UMSEL10)|(3<<UCSZ10);
|
| 79 |
|
|
|
| 80 |
|
|
/* Shut down echo by default. */
|
| 81 |
|
|
buf_write(&kvga_data.writebuf, (uint8_t *)ECHO_OFF, strlen(ECHO_OFF));
|
| 82 |
|
|
buf_write(&kvga_data.writebuf, (uint8_t *)SET_LINEFEED_MODE,
|
| 83 |
|
|
strlen(SET_LINEFEED_MODE));
|
| 84 |
|
|
buf_write(&kvga_data.writebuf, (uint8_t *)DISABLE_AUTO_CR,
|
| 85 |
|
|
strlen(DISABLE_AUTO_CR));
|
| 86 |
|
|
buf_write(&kvga_data.writebuf, (uint8_t *)ENABLE_STATUSLINE,
|
| 87 |
|
|
strlen(ENABLE_STATUSLINE));
|
| 88 |
|
|
buf_write(&kvga_data.writebuf, (uint8_t *)hello, strlen(hello));
|
| 89 |
|
|
/* XXX: Just a dummy-prompt until we have the FPGA doing stuff. */
|
| 90 |
|
|
// buf_write(&kvga_data.writebuf, (uint8_t *)dummyprompt,
|
| 91 |
|
|
// strlen(dummyprompt));
|
| 92 |
|
|
// XXX: Return value not checked.
|
| 93 |
|
|
dispatch_request_make(&igordev_kvga, REQ_TYPE_FLUSH, 0, 0, NULL);
|
| 94 |
|
|
/* Auto linefeed */
|
| 95 |
|
|
// kvga_send((uint8_t *)AUTO_LINEFEED, strlen(AUTO_LINEFEED));
|
| 96 |
|
|
}
|
| 97 |
|
|
|
| 98 |
|
|
// Received a word
|
| 99 |
|
|
ISR(SIG_USART1_RECV)
|
| 100 |
|
|
{
|
| 101 |
|
|
// Read UDR to reset interrupt flag
|
| 102 |
|
|
struct buf *rbuf, *wbuf;
|
| 103 |
|
|
uint8_t data;
|
| 104 |
|
|
|
| 105 |
|
|
igordev_kvga.read_status = IDEV_STATUS_INTR;
|
| 106 |
|
|
/* Store in the buffers. */
|
| 107 |
|
|
data = UDR1;
|
| 108 |
|
|
|
| 109 |
|
|
/* Swallow newlines. */
|
| 110 |
|
|
rbuf = &kvga_data.readbuf;
|
| 111 |
|
|
wbuf = &kvga_data.writebuf;
|
| 112 |
|
|
#define ONESQUARE (MAXBUFLEN / 4)
|
| 113 |
|
|
/*
|
| 114 |
|
|
* If buffer is getting full, don't echo the input to signal that the
|
| 115 |
|
|
* user have to wait
|
| 116 |
|
|
*/
|
| 117 |
|
|
if (buf_writesleft(rbuf) < (ONESQUARE - 1))
|
| 118 |
|
|
return;
|
| 119 |
|
|
|
| 120 |
|
|
buf_write(rbuf, &data, 1);
|
| 121 |
|
|
/* Echo to output buffer. */
|
| 122 |
|
|
// buf_write(wbuf, &data, 1);
|
| 123 |
|
|
// XXX: Return value not checked
|
| 124 |
|
|
// dispatch_request_make(&igordev_kvga, REQ_TYPE_FLUSH, 0, 0, NULL);
|
| 125 |
|
|
/* As a way to allow us to test it. */
|
| 126 |
|
|
// XXX: Return value not checked
|
| 127 |
|
|
// dispatch_request_make(&igordev_kvga, REQ_TYPE_FUNC, 0, 0,
|
| 128 |
|
|
// dispatch_vga_to_usart);
|
| 129 |
|
|
|
| 130 |
|
|
igordev_kvga.read_status = IDEV_STATUS_OK;
|
| 131 |
|
|
}
|
| 132 |
|
|
|
| 133 |
|
|
/*
|
| 134 |
|
|
* Read num bytes from addr and place it into data.
|
| 135 |
|
|
* Data assumed to be a buffer large enough for num bytes.
|
| 136 |
|
|
* Addr here is ignored, since serial is a streaming device.
|
| 137 |
|
|
*/
|
| 138 |
|
|
uint8_t
|
| 139 |
|
|
kvga_recv(uint64_t addr, uint8_t *data, uint8_t num)
|
| 140 |
|
|
{
|
| 141 |
|
|
struct buf *buf;
|
| 142 |
|
|
uint8_t byte;
|
| 143 |
|
|
uint8_t i;
|
| 144 |
|
|
|
| 145 |
|
|
buf = &kvga_data.readbuf;
|
| 146 |
|
|
/* Avoid making larger buffers for now. */
|
| 147 |
|
|
for (i = 0; i < num; i++) {
|
| 148 |
|
|
buf_read(buf, &byte, 1);
|
| 149 |
|
|
if (BUF_EMPTY(buf))
|
| 150 |
|
|
break;
|
| 151 |
|
|
*(data + i) = byte;
|
| 152 |
|
|
}
|
| 153 |
|
|
return (i);
|
| 154 |
|
|
}
|
| 155 |
|
|
|
| 156 |
|
|
/*
|
| 157 |
|
|
k* KVGA transmit, initiates a data transfer by writing to the outputbuffer and
|
| 158 |
|
|
* starting the transfer of the first character.
|
| 159 |
|
|
*/
|
| 160 |
|
|
uint8_t
|
| 161 |
|
|
kvga_send(uint64_t addr, uint8_t *data, uint8_t num)
|
| 162 |
|
|
{
|
| 163 |
|
|
struct buf *buf;
|
| 164 |
|
|
uint8_t i;
|
| 165 |
|
|
/* Transmit only once, and the buffer will be flushed anyway. */
|
| 166 |
|
|
i = 0;
|
| 167 |
|
|
/* If we're not provided with data, just flush it. */
|
| 168 |
|
|
if (num > 0 && data != NULL) {
|
| 169 |
|
|
/* Copy data into write buffer. */
|
| 170 |
|
|
buf = &kvga_data.writebuf;
|
| 171 |
|
|
i = buf_write(buf, data, num);
|
| 172 |
|
|
}
|
| 173 |
|
|
return (i);
|
| 174 |
|
|
}
|
| 175 |
|
|
|
| 176 |
|
|
/* Send whatever we have in the output buffers. */
|
| 177 |
|
|
void
|
| 178 |
|
|
kvga_flush(void)
|
| 179 |
|
|
{
|
| 180 |
|
|
struct buf *buf;
|
| 181 |
|
|
uint8_t data;
|
| 182 |
|
|
|
| 183 |
|
|
igordev_kvga.write_status = IDEV_STATUS_BUSY;
|
| 184 |
|
|
buf = &kvga_data.writebuf;
|
| 185 |
|
|
buf_read(buf, &data, 1);
|
| 186 |
|
|
while (!BUF_EMPTY(buf)) {
|
| 187 |
|
|
/* Wait until output buffer is ready. */
|
| 188 |
|
|
while (!( UCSR1A & (1<<UDRE1)));
|
| 189 |
|
|
|
| 190 |
|
|
UDR1 = data; /* Initiate transfer. */
|
| 191 |
|
|
buf_read(buf, &data, 1);
|
| 192 |
|
|
}
|
| 193 |
|
|
igordev_kvga.write_status = IDEV_STATUS_OK;
|
| 194 |
|
|
}
|