]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/sci.c
Unification of the licence in the scripts, source and header files
[pes-rpp/rpp-lib.git] / rpp / src / drv / sci.c
1 /* Copyright (C) 2012-2013 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Michal Horn <hornmich@fel.cvut.cz>
5  *
6  * This document contains proprietary information belonging to Czech
7  * Technical University in Prague. Passing on and copying of this
8  * document, and communication of its contents is not permitted
9  * without prior written authorization.
10  *
11  * File : sci.c
12  *
13  */
14
15 #include "drv/drv.h"
16
17 static boolean_t crlf_conv_enabled = TRUE;
18
19 void drv_sci_init()
20 {
21         // Low level init
22         sciInit();
23         sciSetBaudrate(serialLine, 115200);
24 }
25
26 void drv_sci_set_baudrate(uint32_t baud)
27 {
28         // Set baudrate
29         sciSetBaudrate(serialLine, baud);
30 }
31
32 /** Declared in ti_drv_sci.c */
33 extern tBuffer sciOutBuffer;
34 extern tBuffer sciInBuffer;
35
36 uint16_t drv_sci_available()
37 {
38         return (uint16_t)uxQueueMessagesWaiting(sciInBuffer.buf);
39 }
40
41
42 int8_t drv_sci_receive(uint32_t amount, uint8_t *buffer, portTickType wait)
43 {
44         if (sciInBuffer.buf == NULL)
45                 return FAILURE;
46
47         if (xSemaphoreTake(sciInBuffer.mutex, wait) != pdTRUE)
48                 return FAILURE;
49
50         // If non block mode, return if not enough data is available
51         if (wait == 0)
52                 if (drv_sci_available() < amount) {
53                         xSemaphoreGive(sciInBuffer.mutex);
54                         return FAILURE;
55                 }
56
57         int i = 0;
58         unsigned portBASE_TYPE status;
59         while (i < amount) {
60                 status = xQueueReceive(sciInBuffer.buf, &buffer[i], wait);
61                 if (status != pdTRUE) {
62                         xSemaphoreGive(sciInBuffer.mutex);
63                         return FAILURE;
64                 }
65                 i++;
66         }
67
68         xSemaphoreGive(sciInBuffer.mutex);
69         return SUCCESS;
70 }
71
72 static int crlf_conv(uint8_t ch_in, uint8_t *ch_out)
73 {
74         static bool was_cr = false;
75
76         if (crlf_conv_enabled)
77                 if (ch_in == '\n' && !was_cr) {
78                         *ch_out = '\r';
79                         was_cr = true;
80                         return 0; // Retry the same char next time
81                 }
82         *ch_out = ch_in;
83         was_cr = (ch_in == '\r');
84         return 1; // Move to the next character
85 }
86
87 /**
88  * Non-blocking send.
89  *
90  * Sends data to the serial line without blocking. If the hardware TX
91  * buffer is not free, it busy-waits.
92  *
93  * @param length
94  * @param data
95  */
96 void drv_sci_send_imm(uint32_t length, uint8_t *data)
97 {
98         uint8_t ch;
99
100         while (length > 0) {
101                 int ofs = crlf_conv(*data, &ch);
102                 length -= ofs;
103                 data += ofs;
104                 while (!(serialLine->FLR & SCI_TX_INT)) ;  /* wait till previous char was sent */
105                 serialLine->TD = ch;
106         }
107 }
108
109 int8_t drv_sci_send_try_append(uint32_t length, uint8_t *data)
110 {
111         uint8_t ch;
112
113         if (sciOutBuffer.buf == NULL)
114                 return FAILURE;
115
116         portBASE_TYPE ret = pdTRUE;
117         while (length > 0) {
118                 int ofs = crlf_conv(*data, &ch);
119                 length -= ofs;
120                 data += ofs;
121
122                 if (!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS)
123                         if (!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
124                                 sciOutBuffer.flags |= BUF_TRANSFER_IN_PROGRESS;
125                                 serialLine->SETINT = SCI_TX_INT;        // Start new transfer by sending first byte
126                                 serialLine->TD     = ch;
127                                 continue;
128                         }
129
130                 ret = xQueueSendToBackFromISR(sciOutBuffer.buf, (void *)&ch, NULL);
131                 if (ret != pdTRUE)
132                         break;
133                 ret = length;
134         }
135         return ret;
136 }
137
138 int8_t drv_sci_send(uint32_t length, uint8_t *data, portTickType wait)
139 {
140         uint8_t ch;
141
142         if (sciOutBuffer.buf == NULL)
143                 return FAILURE;
144
145         if (xSemaphoreTake(sciOutBuffer.mutex, wait) != pdTRUE)
146                 return FAILURE;
147
148         portBASE_TYPE ret = pdTRUE;
149         while (length > 0) {
150                 int ofs = crlf_conv(*data, &ch);
151                 length -= ofs;
152                 data += ofs;
153
154                 if (!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
155                         taskENTER_CRITICAL();
156                         if (!sciOutBuffer.flags & BUF_TRANSFER_IN_PROGRESS) {
157                                 sciOutBuffer.flags |= BUF_TRANSFER_IN_PROGRESS;
158                                 serialLine->SETINT = SCI_TX_INT;        // Start new transfer by sending first byte
159                                 serialLine->TD     = ch;
160                                 taskEXIT_CRITICAL();
161                                 continue;
162                         }
163                         taskEXIT_CRITICAL();
164                 }
165
166                 ret = xQueueSend(sciOutBuffer.buf, (void *)&ch, wait);
167                 if (ret != pdTRUE) {
168                         xSemaphoreGive(sciOutBuffer.mutex);
169                         return FAILURE;
170                 }
171         }
172
173         xSemaphoreGive(sciOutBuffer.mutex);
174         return SUCCESS;
175 }
176
177
178 int8_t drv_sci_flush_buffer(tBuffer *buffer)
179 {
180         if (uxQueueMessagesWaiting(buffer->buf) == 0)
181                 return FAILURE;
182         xSemaphoreTake(buffer->mutex, portMAX_DELAY);
183         // FIXME: FreeRTOS 7.0.2 doesn't have xQueueReset
184         //xQueueReset(buffer->buf);
185         // FIXME Workaround
186         uint8_t dummy = 0;
187         while (uxQueueMessagesWaiting(buffer->buf) > 0)
188                 xQueueReceive(buffer->buf, &dummy, 0);
189         ////////////////////
190         xSemaphoreGive(buffer->mutex);
191         return SUCCESS;
192 }
193
194 int8_t drv_sci_flush(boolean_t buf)
195 {
196         if (buf)
197                 return drv_sci_flush_buffer(&sciInBuffer);
198         return drv_sci_flush_buffer(&sciOutBuffer);
199 }
200
201 void drv_sci_set_crlf_conv_en(boolean_t enable)
202 {
203         crlf_conv_enabled = enable;
204 }
205
206 boolean_t drv_sci_get_crlf_conv_en()
207 {
208         return crlf_conv_enabled;
209 }