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

Subversion Repositories igor

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

powered by: WebSVN 2.1.0

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