]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/sci.c
Add automatic CRLF conversion to SCI output
[pes-rpp/rpp-lib.git] / rpp / src / drv / sci.c
1 #include "drv/drv.h"
2
3 void drv_sci_init()
4 {
5     // Low level init
6     sciInit();
7 }
8
9 void drv_sci_set_baudrate(uint32_t baud)
10 {
11     // Set baudrate
12     sciSetBaudrate(sciREG, baud);
13 }
14
15 /** Declared in ti_drv_sci.c */
16 extern tBuffer sciOutBuffer;
17 extern tBuffer sciInBuffer;
18
19 uint16_t drv_sci_available()
20 {
21     return (uint16_t)uxQueueMessagesWaiting(sciInBuffer.buf);
22 }
23
24
25 int8_t drv_sci_receive(uint32_t amount, uint8_t* buffer, portTickType wait)
26 {
27     if(sciInBuffer.buf == NULL) {
28         return FAILURE;
29     }
30
31     if(xSemaphoreTake(sciInBuffer.mutex, wait) != pdTRUE) {
32         return FAILURE;
33     }
34
35     // If non block mode, return if not enough data is available
36     if(wait == 0) {
37         if(drv_sci_available() < amount) {
38             xSemaphoreGive(sciInBuffer.mutex);
39             return FAILURE;
40         }
41     }
42
43     int i = 0;
44     unsigned portBASE_TYPE status;
45     while(i < amount) {
46         status = xQueueReceive(sciInBuffer.buf, &buffer[i], wait);
47         if(status != pdTRUE) {
48             xSemaphoreGive(sciInBuffer.mutex);
49             return FAILURE;
50         }
51         i++;
52     }
53
54     xSemaphoreGive(sciInBuffer.mutex);
55     return SUCCESS;
56 }
57
58 static int crlf_conv(uint8_t ch_in, uint8_t *ch_out)
59 {
60         static bool was_cr = false;
61         if (ch_in == '\n' && !was_cr) {
62                 *ch_out = '\r';
63                 was_cr = true;
64                 return 0; // Retry the same char next time
65         }
66         *ch_out = ch_in;
67         was_cr = (ch_in == '\r');
68         return 1; // Move to the next character
69 }
70
71
72 int8_t drv_sci_send(uint32_t length, uint8_t* data, portTickType wait)
73 {
74         uint8_t ch;
75     if(sciOutBuffer.buf == NULL) {
76         return FAILURE;
77     }
78
79     if(xSemaphoreTake(sciOutBuffer.mutex, wait) != pdTRUE) {
80         return FAILURE;
81     }
82
83     portBASE_TYPE ret = pdTRUE;
84     while(length > 0) {
85         int ofs = crlf_conv(*data, &ch);
86         length -= ofs;
87         data += ofs;
88
89         if(!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
90                 taskENTER_CRITICAL();
91                 if (!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
92                     sciOutBuffer.flags |= BUF_TRANSFER_IN_PROGRESS;
93                     sciREG->SETINT = SCI_TX_INT;    // Start new transfer by sending first byte
94                     sciREG->TD     = ch;
95                     taskEXIT_CRITICAL();
96                     continue;
97                 }
98                 taskEXIT_CRITICAL();
99         }
100
101         ret = xQueueSend(sciOutBuffer.buf, (void*)&ch, wait);
102         if(ret != pdTRUE) {
103             xSemaphoreGive(sciOutBuffer.mutex);
104             return FAILURE;
105         }
106     }
107
108     xSemaphoreGive(sciOutBuffer.mutex);
109     return SUCCESS;
110 }
111
112
113 int8_t drv_sci_flush_buffer(tBuffer* buffer)
114 {
115     if(uxQueueMessagesWaiting(buffer->buf) == 0) {
116         return FAILURE;
117     }
118     xSemaphoreTake(buffer->mutex, portMAX_DELAY);
119     // FIXME: FreeRTOS 7.0.2 doesn't have xQueueReset
120     //xQueueReset(buffer->buf);
121     // FIXME Workaround
122     uint8_t dummy = 0;
123     while(uxQueueMessagesWaiting(buffer->buf) > 0) {
124         xQueueReceive(buffer->buf, &dummy, 0);
125     }
126     ////////////////////
127     xSemaphoreGive(buffer->mutex);
128     return SUCCESS;
129 }
130
131 int8_t drv_sci_flush(boolean_t buf)
132 {
133     if(buf) {
134         return drv_sci_flush_buffer(&sciInBuffer);
135     }
136     return drv_sci_flush_buffer(&sciOutBuffer);
137 }