OpenCores
URL https://opencores.org/ocsvn/igor/igor/trunk

Subversion Repositories igor

[/] [igor/] [trunk/] [avr/] [eth-test/] [dev/] [usart.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 atypic
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <global.h>
4
#include <stdint.h>
5
#include <device.h>
6
#include <dispatch.h>
7
#include <req.h>
8
#include <stdlib.h>
9
#include <string.h>
10
 
11
#define BAUD 9600
12
#define MUBRR ((FOSC/16/BAUD)-1)
13
 
14
static struct {
15
        struct buf readbuf;
16
        struct buf writebuf;
17
} usart_data;
18
 
19
#define XON     0x11
20
#define XOFF    0x13
21
/* Internal flow control. */
22
uint8_t xflow_local;
23
/* Internal flow control for transmit. */
24
uint8_t xflow_state_transmit;
25
/* External flow control. */
26
uint8_t xflow_remote;
27
 
28
static int8_t usart_send_data(void);
29
static igordev_read_fn_t usart_recv;
30
static igordev_write_fn_t usart_send;
31
static igordev_init_fn_t init;
32
static igordev_flush_fn_t usart_flush;
33
 
34
/* XXX: Not completed. */
35
struct igordev igordev_usart = {
36
        .init = init,
37
        .read = usart_recv,
38
        .write = usart_send,
39
        .flush = usart_flush,
40
        .read_status = 0,
41
        .write_status = 0,
42
        .priv = &usart_data
43
};
44
 
45
 
46
void init() {
47
        /* Set internal stuff first. */
48
        const char *uhello = "Hello, world from USART!\r\n";
49
        volatile struct req *req;
50
        buf_init(&usart_data.readbuf);
51
        buf_init(&usart_data.writebuf);
52
        igordev_usart.read_status = igordev_usart.write_status = IDEV_STATUS_OK;
53
        xflow_local = xflow_remote = xflow_state_transmit = XON;
54
        igordev_usart.id = (CAN_READ | CAN_WRITE |
55
            (DEVTYPE_SERIAL << DEVTYPE_OFFSET));
56
 
57
        // Disable powersaving
58
        PRR0 &= ~(1<<PRUSART0);
59
 
60
        // Set tranfser speed
61
        UBRR0L = (uint8_t)MUBRR;
62
        UBRR0H = (uint8_t)(MUBRR>>8);
63
 
64
        // Enable reciever, transmitter and interrupts ( Not active until global interrupts are enabled)
65
        UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
66
 
67
        // Set format, stopbits, mode: 8n1
68
        UCSR0C = (0<<USBS0)|(0<<UPM01)|(0<<UPM00)|(0<<UMSEL01)|(0<<UMSEL00)|(3<<UCSZ00);
69
        buf_write(&usart_data.writebuf, (uint8_t *)uhello, strlen(uhello));
70
        req = req_make(&igordev_usart, REQ_TYPE_FLUSH, 0, 0, NULL);
71
        if (req != NULL)
72
                dispatch_request_notify(req);
73
}
74
 
75
// Received a word
76
ISR(SIG_USART0_RECV) {
77
        // Read UDR to reset interrupt flag
78
        struct buf *buf;
79
        uint8_t data;
80
 
81
        igordev_usart.read_status = IDEV_STATUS_INTR;
82
        /* Store in the buffers. */
83
        data = UDR0;
84
        /* If we received external flow control signal. */
85
        if (data == XOFF || data == XON) {
86
                xflow_remote = data;
87
                igordev_usart.read_status = IDEV_STATUS_OK;
88
                return;
89
        }
90
 
91
        buf = &usart_data.readbuf;
92
#define ONESQUARE (MAXBUFLEN / 4)
93
        if (buf_writesleft(buf) < (ONESQUARE - 1))
94
                xflow_local = XOFF;
95
 
96
        buf_write(buf, &data, 1);
97
        igordev_usart.read_status = IDEV_STATUS_OK;
98
}
99
 
100
/*
101
 * Read num bytes from addr and place it into data.
102
 * Data assumed to be a buffer large enough for num bytes.
103
 * Addr here is ignored, since serial is a streaming device.
104
 */
105
uint8_t
106
usart_recv(uint64_t addr, uint8_t *data, uint8_t num)
107
{
108
        struct buf *buf;
109
        uint8_t byte;
110
        uint8_t i;
111
 
112
        buf = &usart_data.readbuf;
113
        /* Avoid making larger buffers for now. */
114
        for (i = 0; i < num; i++) {
115
                buf_read(buf, &byte, 1);
116
                if (BUF_EMPTY(buf))
117
                        break;
118
                *(data + i) = byte;
119
        }
120
        return (i);
121
}
122
 
123
/*
124
 * Example of transmit. Currently initiates the write and let the TX interrupt
125
 * handle the rest.
126
 */
127
uint8_t
128
usart_send(uint64_t addr, uint8_t *data, uint8_t num)
129
{
130
        struct buf *buf;
131
        uint8_t i = 0;
132
        /* Transmit only once, and the buffer will be flushed anyway. */
133
        /* Only output data if we're provided with data. */
134
        if (num > 0 && data != NULL) {
135
                /* Copy data into write buffer. */
136
                buf = &usart_data.writebuf;
137
                i = buf_write(buf, data, num);
138
        }
139
        return (i);
140
}
141
 
142
/* Send whatever we have in the output buffer. */
143
static void
144
usart_flush(void)
145
{
146
        struct buf *buf;
147
        buf = &usart_data.writebuf;
148
 
149
        igordev_usart.write_status = IDEV_STATUS_BUSY;
150
        /* Flush as long as it is ok. */
151
        while (!BUF_EMPTY(buf) && usart_send_data() == 0);
152
        igordev_usart.write_status = IDEV_STATUS_OK;
153
}
154
 
155
/* Sends the next byte in the buffer. */
156
static int8_t
157
usart_send_data(void)
158
{
159
        struct buf *buf;
160
        uint8_t data;
161
 
162
        /* Cannot send data yet. */
163
        if (xflow_remote == XOFF)
164
                return (-1);
165
 
166
        buf = &usart_data.writebuf;
167
        switch (xflow_local) {
168
        case XON:
169
                /* If we have few reads left, make sure we can get more. */
170
                buf_read(buf, &data, 1);
171
                if (BUF_EMPTY(buf))
172
                        return (-1);
173
                break;
174
        case XOFF:
175
                /* If we have not signalled OK again, do it. */
176
                if (buf_readsleft(buf) >= (MAXBUFLEN - ONESQUARE) &&
177
                    xflow_state_transmit == XOFF) {
178
                        data = XON;
179
                        xflow_state_transmit = XON;
180
                        xflow_local = XON;
181
                        break;
182
                }
183
                /* If we have not sent the xflow_state signal, do it. */
184
                if (xflow_state_transmit == XON) {
185
                        data = XOFF;
186
                        xflow_state_transmit = XOFF;
187
                        break;
188
                }
189
                return (-1);
190
        default:
191
                return (-1);
192
        }
193
        while (!(UCSR0A & (1<<UDRE0)));
194
        UDR0 = data; /* Initiate transfer. */
195
        return (0);
196
}
197
 
198
#if 0
199
void
200
usart_loopback(void *arg)
201
{
202
        struct buf *in;
203
        uint8_t data[MAXBUFLEN];
204
        uint8_t i, num;
205
 
206
        cli();
207
        in = &usart_data.readbuf;
208
        /* Fill output buffer from input buffer. */
209
        i = 0;
210
        num = buf_read(in, data, MAXBUFLEN);
211
        usart_send(data, num);
212
        sei();
213
}
214
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.