MMEx with SPI Slave to allow legacy devices to communicate with modern media such as USB, SD cards, the internet and all of the mbed\'s other interfaces

Dependencies:   NetServices MSCUsbHost mbed TMP102 SDFileSystem

Committer:
DeMein
Date:
Sun Feb 27 18:54:40 2011 +0000
Revision:
0:67a55a82ce06
Version as submitted to the NXP Design Challenge

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DeMein 0:67a55a82ce06 1 /* MMEx for MBED - SPI interfacing and ringbuffer functions
DeMein 0:67a55a82ce06 2 * Copyright (c) 2011 MK
DeMein 0:67a55a82ce06 3 *
DeMein 0:67a55a82ce06 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
DeMein 0:67a55a82ce06 5 * of this software and associated documentation files (the "Software"), to deal
DeMein 0:67a55a82ce06 6 * in the Software without restriction, including without limitation the rights
DeMein 0:67a55a82ce06 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
DeMein 0:67a55a82ce06 8 * copies of the Software, and to permit persons to whom the Software is
DeMein 0:67a55a82ce06 9 * furnished to do so, subject to the following conditions:
DeMein 0:67a55a82ce06 10 *
DeMein 0:67a55a82ce06 11 * The above copyright notice and this permission notice shall be included in
DeMein 0:67a55a82ce06 12 * all copies or substantial portions of the Software.
DeMein 0:67a55a82ce06 13 *
DeMein 0:67a55a82ce06 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
DeMein 0:67a55a82ce06 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
DeMein 0:67a55a82ce06 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
DeMein 0:67a55a82ce06 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
DeMein 0:67a55a82ce06 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
DeMein 0:67a55a82ce06 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
DeMein 0:67a55a82ce06 20 * THE SOFTWARE.
DeMein 0:67a55a82ce06 21 */
DeMein 0:67a55a82ce06 22
DeMein 0:67a55a82ce06 23 /**
DeMein 0:67a55a82ce06 24 \file spissp.cpp
DeMein 0:67a55a82ce06 25 \brief SPI interfacing and ringbuffer functions
DeMein 0:67a55a82ce06 26 */
DeMein 0:67a55a82ce06 27
DeMein 0:67a55a82ce06 28 #include "spissp.h"
DeMein 0:67a55a82ce06 29
DeMein 0:67a55a82ce06 30 /** Library for the interrupt driven SPI SLave
DeMein 0:67a55a82ce06 31 *
DeMein 0:67a55a82ce06 32 */
DeMein 0:67a55a82ce06 33 spislirq *spislirq::instance;
DeMein 0:67a55a82ce06 34
DeMein 0:67a55a82ce06 35 /** Library for the interrupt driven SPI SLave
DeMein 0:67a55a82ce06 36 *
DeMein 0:67a55a82ce06 37 */
DeMein 0:67a55a82ce06 38 spislirq::spislirq (int PortNum): smldl(p11, p12, p13, p14),
DeMein 0:67a55a82ce06 39 pc(USBTX, USBRX, "pc"), _led4(LED4)
DeMein 0:67a55a82ce06 40 { }
DeMein 0:67a55a82ce06 41
DeMein 0:67a55a82ce06 42 /** initialization of SPI Slave and buffers
DeMein 0:67a55a82ce06 43 *
DeMein 0:67a55a82ce06 44 */
DeMein 0:67a55a82ce06 45 void spislirq::init() {
DeMein 0:67a55a82ce06 46 uint32_t tmp;
DeMein 0:67a55a82ce06 47
DeMein 0:67a55a82ce06 48 smldl.format(8,3); // SPI format: 8 bits, mode 3
DeMein 0:67a55a82ce06 49 // mode | POL PHA
DeMein 0:67a55a82ce06 50 // -----+--------
DeMein 0:67a55a82ce06 51 // 0 | 0 0
DeMein 0:67a55a82ce06 52 // 1 | 0 1
DeMein 0:67a55a82ce06 53 // 2 | 1 0
DeMein 0:67a55a82ce06 54 // 3 | 1 1
DeMein 0:67a55a82ce06 55 smldl.frequency(1000000); // more or less universal speed at 1 MHz
DeMein 0:67a55a82ce06 56 // determines time out IRQ time!
DeMein 0:67a55a82ce06 57
DeMein 0:67a55a82ce06 58 // initialize buffers
DeMein 0:67a55a82ce06 59 rx_in = 0;
DeMein 0:67a55a82ce06 60 rx_out = 0;
DeMein 0:67a55a82ce06 61 tx_in = 0;
DeMein 0:67a55a82ce06 62 tx_out = 0;
DeMein 0:67a55a82ce06 63
DeMein 0:67a55a82ce06 64 // add code here to set the SSP interrupt register and enable interrupts
DeMein 0:67a55a82ce06 65 // setup IMSC Interrupt Mask Set/Clear Register
DeMein 0:67a55a82ce06 66 // only enable interrupts for RX FIFO half full and RX timeout
DeMein 0:67a55a82ce06 67 tmp = (SSP_IMSC_RT | SSP_IMSC_RX) & SSP_IMSC_BITMASK;
DeMein 0:67a55a82ce06 68
DeMein 0:67a55a82ce06 69 LPC_SSP0->IMSC = tmp;
DeMein 0:67a55a82ce06 70
DeMein 0:67a55a82ce06 71 // attach our interrupt service routine
DeMein 0:67a55a82ce06 72 instance = this;
DeMein 0:67a55a82ce06 73 NVIC_SetVector(SSP0_IRQn, (uint32_t)&_spi_isr);
DeMein 0:67a55a82ce06 74 enable_irq();
DeMein 0:67a55a82ce06 75 }
DeMein 0:67a55a82ce06 76
DeMein 0:67a55a82ce06 77 /** disable SSP0 interrupts
DeMein 0:67a55a82ce06 78 * will discard the byte if buffer full
DeMein 0:67a55a82ce06 79 */
DeMein 0:67a55a82ce06 80 void spislirq::disable_irq(void)
DeMein 0:67a55a82ce06 81 {
DeMein 0:67a55a82ce06 82 NVIC_DisableIRQ(SSP0_IRQn);
DeMein 0:67a55a82ce06 83 }
DeMein 0:67a55a82ce06 84
DeMein 0:67a55a82ce06 85 /** enable SSP0 interrupts
DeMein 0:67a55a82ce06 86 * will discard the byte if buffer full
DeMein 0:67a55a82ce06 87 */
DeMein 0:67a55a82ce06 88 void spislirq::enable_irq(void)
DeMein 0:67a55a82ce06 89 {
DeMein 0:67a55a82ce06 90 NVIC_EnableIRQ(SSP0_IRQn);
DeMein 0:67a55a82ce06 91 }
DeMein 0:67a55a82ce06 92
DeMein 0:67a55a82ce06 93 /** instantiation of isr
DeMein 0:67a55a82ce06 94 * will discard the byte if buffer full
DeMein 0:67a55a82ce06 95 */
DeMein 0:67a55a82ce06 96 void spislirq::_spi_isr(void)
DeMein 0:67a55a82ce06 97 {
DeMein 0:67a55a82ce06 98 instance->spi_isr();
DeMein 0:67a55a82ce06 99 }
DeMein 0:67a55a82ce06 100
DeMein 0:67a55a82ce06 101 /** add one byte to the transmit buffer, no blocking, no protocol
DeMein 0:67a55a82ce06 102 * will discard the byte if buffer full
DeMein 0:67a55a82ce06 103 *
DeMein 0:67a55a82ce06 104 * @param c byte to send
DeMein 0:67a55a82ce06 105 *
DeMein 0:67a55a82ce06 106 */
DeMein 0:67a55a82ce06 107 void spislirq::txx_add(unsigned char c) {
DeMein 0:67a55a82ce06 108 if (!tx_full()) {
DeMein 0:67a55a82ce06 109 txxbuf[tx_in] = c;
DeMein 0:67a55a82ce06 110 tx_in = (tx_in + 1) % bufsize;
DeMein 0:67a55a82ce06 111 }
DeMein 0:67a55a82ce06 112 }
DeMein 0:67a55a82ce06 113
DeMein 0:67a55a82ce06 114 /** SPI SLave interrupt service routine
DeMein 0:67a55a82ce06 115 *
DeMein 0:67a55a82ce06 116 */
DeMein 0:67a55a82ce06 117 void spislirq::spi_isr(void)
DeMein 0:67a55a82ce06 118 {
DeMein 0:67a55a82ce06 119 uint16_t inp;
DeMein 0:67a55a82ce06 120
DeMein 0:67a55a82ce06 121 _led4 = !_led4; // visualize we are in the isr
DeMein 0:67a55a82ce06 122
DeMein 0:67a55a82ce06 123 // we get in the ISR when there is at least one input char pending
DeMein 0:67a55a82ce06 124 // IRQ sources: - RX FIFO at least half full (4 chars)
DeMein 0:67a55a82ce06 125 // - RX FIFO not empty and not read from a time-out period
DeMein 0:67a55a82ce06 126
DeMein 0:67a55a82ce06 127
DeMein 0:67a55a82ce06 128 // first we check if there is enough room left in the RX buffer
DeMein 0:67a55a82ce06 129 // if there is less than 10% left we signal this to the SPI Master
DeMein 0:67a55a82ce06 130 // is is very unlikely that the TX buffer is full when there is risk for
DeMein 0:67a55a82ce06 131 // overrun, but we can always send the '>B' the next time, as there will
DeMein 0:67a55a82ce06 132 // be more than 20 free chars in the buffer
DeMein 0:67a55a82ce06 133 if (rx_perc() > 90) {
DeMein 0:67a55a82ce06 134 txx_add('>');
DeMein 0:67a55a82ce06 135 txx_add('B');
DeMein 0:67a55a82ce06 136 }
DeMein 0:67a55a82ce06 137
DeMein 0:67a55a82ce06 138 // now do the real work, just like in spi_rw():
DeMein 0:67a55a82ce06 139 // 1. fill output FIFO with data from TX buffer
DeMein 0:67a55a82ce06 140
DeMein 0:67a55a82ce06 141 while ((!tx_empty()) && tx_fifo_notfull) {
DeMein 0:67a55a82ce06 142 // we can indeed try to transmit data
DeMein 0:67a55a82ce06 143 // put as much data as possible in the transmit FIFO
DeMein 0:67a55a82ce06 144 LPC_SSP0->DR = (uint16_t)txxbuf[tx_out];
DeMein 0:67a55a82ce06 145 tx_out = (tx_out + 1) % bufsize;
DeMein 0:67a55a82ce06 146 }
DeMein 0:67a55a82ce06 147
DeMein 0:67a55a82ce06 148 // in case the TX FIFO and output buffer are empty, add 0x00
DeMein 0:67a55a82ce06 149 if (tx_empty() && tx_fifo_empty) {
DeMein 0:67a55a82ce06 150 LPC_SSP0->DR = (uint16_t)0x00;
DeMein 0:67a55a82ce06 151 }
DeMein 0:67a55a82ce06 152
DeMein 0:67a55a82ce06 153 if irq_RTMIS {
DeMein 0:67a55a82ce06 154 // interrupt on timeout, clear RTIC to clear interrupt
DeMein 0:67a55a82ce06 155 LPC_SSP0->ICR = (SSP_ICR_RT & SSP_ICR_BITMASK);
DeMein 0:67a55a82ce06 156 }
DeMein 0:67a55a82ce06 157
DeMein 0:67a55a82ce06 158 // we must ensure that always the complete RX FIFO is read
DeMein 0:67a55a82ce06 159 // when the RX buffer is really full, characters are discarded
DeMein 0:67a55a82ce06 160 while (rx_fifo_notempty) {
DeMein 0:67a55a82ce06 161 inp = LPC_SSP0->DR;
DeMein 0:67a55a82ce06 162 if ((inp != 0x00) && !rx_full()) {
DeMein 0:67a55a82ce06 163 // received value only interesting when not 0x00
DeMein 0:67a55a82ce06 164 rxxbuf[rx_in] = inp;
DeMein 0:67a55a82ce06 165 rx_in = (rx_in + 1) % bufsize;
DeMein 0:67a55a82ce06 166 }
DeMein 0:67a55a82ce06 167 }
DeMein 0:67a55a82ce06 168 }
DeMein 0:67a55a82ce06 169
DeMein 0:67a55a82ce06 170
DeMein 0:67a55a82ce06 171 /** returns the number of bytes available in the transmit buffer
DeMein 0:67a55a82ce06 172 *
DeMein 0:67a55a82ce06 173 * @return available space in transmit buffer
DeMein 0:67a55a82ce06 174 */
DeMein 0:67a55a82ce06 175 int spislirq::tx_room() {
DeMein 0:67a55a82ce06 176 if (tx_in < tx_out) {
DeMein 0:67a55a82ce06 177 return(tx_out - tx_in - 1);
DeMein 0:67a55a82ce06 178 } else {
DeMein 0:67a55a82ce06 179 return(bufsize - tx_in + tx_out - 1);
DeMein 0:67a55a82ce06 180 }
DeMein 0:67a55a82ce06 181 }
DeMein 0:67a55a82ce06 182
DeMein 0:67a55a82ce06 183 /** returns the percentage used in the transmit buffer
DeMein 0:67a55a82ce06 184 *
DeMein 0:67a55a82ce06 185 * @return percentage from 0 to 100
DeMein 0:67a55a82ce06 186 */
DeMein 0:67a55a82ce06 187 int spislirq::tx_perc() {
DeMein 0:67a55a82ce06 188 // returns the percentage used in the transmit buffer
DeMein 0:67a55a82ce06 189 return(100 * tx_use() / bufsize);
DeMein 0:67a55a82ce06 190 }
DeMein 0:67a55a82ce06 191
DeMein 0:67a55a82ce06 192 /** returns the percentage used in the receive buffer
DeMein 0:67a55a82ce06 193 *
DeMein 0:67a55a82ce06 194 * @return percentage from 0 to 100
DeMein 0:67a55a82ce06 195 */
DeMein 0:67a55a82ce06 196 int spislirq::rx_perc() {
DeMein 0:67a55a82ce06 197 // returns the percentage used in the transmit buffer
DeMein 0:67a55a82ce06 198 return(100 * rx_use() / bufsize);
DeMein 0:67a55a82ce06 199 }
DeMein 0:67a55a82ce06 200
DeMein 0:67a55a82ce06 201
DeMein 0:67a55a82ce06 202 /** returns the amount af actual bytes used in the transmit buffer
DeMein 0:67a55a82ce06 203 *
DeMein 0:67a55a82ce06 204 * @return bytes used in transmit buffer
DeMein 0:67a55a82ce06 205 */
DeMein 0:67a55a82ce06 206 int spislirq::tx_use() {
DeMein 0:67a55a82ce06 207 return(bufsize - tx_room() - 1);
DeMein 0:67a55a82ce06 208 }
DeMein 0:67a55a82ce06 209
DeMein 0:67a55a82ce06 210 /** returns the number of bytes available in the receive buffer
DeMein 0:67a55a82ce06 211 *
DeMein 0:67a55a82ce06 212 * @return available space in transmit buffer
DeMein 0:67a55a82ce06 213 */
DeMein 0:67a55a82ce06 214 int spislirq::rx_room() {
DeMein 0:67a55a82ce06 215 if (rx_in < rx_out) {
DeMein 0:67a55a82ce06 216 return(rx_out - rx_in - 1);
DeMein 0:67a55a82ce06 217 } else {
DeMein 0:67a55a82ce06 218 return(bufsize - rx_in + rx_out -1);
DeMein 0:67a55a82ce06 219 }
DeMein 0:67a55a82ce06 220 }
DeMein 0:67a55a82ce06 221
DeMein 0:67a55a82ce06 222 /** returns the amount af actual bytes used in the receive buffer
DeMein 0:67a55a82ce06 223 *
DeMein 0:67a55a82ce06 224 * @return bytes used in receive buffer
DeMein 0:67a55a82ce06 225 */
DeMein 0:67a55a82ce06 226 int spislirq::rx_use() {
DeMein 0:67a55a82ce06 227 return(bufsize - rx_room() - 1);
DeMein 0:67a55a82ce06 228 }
DeMein 0:67a55a82ce06 229
DeMein 0:67a55a82ce06 230 /** empties the transmit buffer
DeMein 0:67a55a82ce06 231 */
DeMein 0:67a55a82ce06 232 void spislirq::flush_tx() {
DeMein 0:67a55a82ce06 233 tx_out = tx_in = 0;
DeMein 0:67a55a82ce06 234 }
DeMein 0:67a55a82ce06 235
DeMein 0:67a55a82ce06 236 /** empties the receive buffer
DeMein 0:67a55a82ce06 237 */
DeMein 0:67a55a82ce06 238 void spislirq::flush_rx() {
DeMein 0:67a55a82ce06 239 rx_out = rx_in = 0;
DeMein 0:67a55a82ce06 240 }
DeMein 0:67a55a82ce06 241
DeMein 0:67a55a82ce06 242 /** check if the TX buffer is empty
DeMein 0:67a55a82ce06 243 * @return true if the TX buffer is empty
DeMein 0:67a55a82ce06 244 */
DeMein 0:67a55a82ce06 245 bool spislirq::tx_empty() {
DeMein 0:67a55a82ce06 246 return (tx_in == tx_out);
DeMein 0:67a55a82ce06 247 }
DeMein 0:67a55a82ce06 248
DeMein 0:67a55a82ce06 249 /** check if the TX buffer is full
DeMein 0:67a55a82ce06 250 * @return true if the TX buffer is full
DeMein 0:67a55a82ce06 251 */
DeMein 0:67a55a82ce06 252 bool spislirq::tx_full() {
DeMein 0:67a55a82ce06 253 return(((tx_in + 1) % bufsize) == tx_out);
DeMein 0:67a55a82ce06 254 }
DeMein 0:67a55a82ce06 255
DeMein 0:67a55a82ce06 256 /** check if the RX buffer is empty
DeMein 0:67a55a82ce06 257 * @return true if the RX buffer is empty
DeMein 0:67a55a82ce06 258 */
DeMein 0:67a55a82ce06 259 bool spislirq::rx_empty() {
DeMein 0:67a55a82ce06 260 return(rx_in == rx_out);
DeMein 0:67a55a82ce06 261 }
DeMein 0:67a55a82ce06 262
DeMein 0:67a55a82ce06 263 /** check if the RX buffer is full
DeMein 0:67a55a82ce06 264 * @return true if the RX buffer is full
DeMein 0:67a55a82ce06 265 */
DeMein 0:67a55a82ce06 266 bool spislirq::rx_full() {
DeMein 0:67a55a82ce06 267 return(((rx_in + 1) % bufsize) == rx_out);
DeMein 0:67a55a82ce06 268 }
DeMein 0:67a55a82ce06 269
DeMein 0:67a55a82ce06 270 /** add one byte to the transmit buffer, no protocol handling is done
DeMein 0:67a55a82ce06 271 *
DeMein 0:67a55a82ce06 272 * @param Bt byte to send
DeMein 0:67a55a82ce06 273 * @return 0 when succesfull, will block until there is room in the buffer
DeMein 0:67a55a82ce06 274 *
DeMein 0:67a55a82ce06 275 */
DeMein 0:67a55a82ce06 276 int spislirq::tx_add(unsigned char c) {
DeMein 0:67a55a82ce06 277 while (tx_full()) {
DeMein 0:67a55a82ce06 278 do_callback();
DeMein 0:67a55a82ce06 279 wait_ms(1);
DeMein 0:67a55a82ce06 280 }
DeMein 0:67a55a82ce06 281 do_callback();
DeMein 0:67a55a82ce06 282 disable_irq();
DeMein 0:67a55a82ce06 283 if (!tx_full()) {
DeMein 0:67a55a82ce06 284 txxbuf[tx_in] = c;
DeMein 0:67a55a82ce06 285 tx_in = (tx_in + 1) % bufsize;
DeMein 0:67a55a82ce06 286 enable_irq();
DeMein 0:67a55a82ce06 287 // DBG_outchar(c);
DeMein 0:67a55a82ce06 288 return 0;
DeMein 0:67a55a82ce06 289 } else {
DeMein 0:67a55a82ce06 290 enable_irq();
DeMein 0:67a55a82ce06 291 return -1;
DeMein 0:67a55a82ce06 292 }
DeMein 0:67a55a82ce06 293 }
DeMein 0:67a55a82ce06 294
DeMein 0:67a55a82ce06 295 /** add one byte to the transmit buffer with protocol handling,
DeMein 0:67a55a82ce06 296 * function will block until there is room in the transmit buffer
DeMein 0:67a55a82ce06 297 *
DeMein 0:67a55a82ce06 298 * @param Bt byte to send
DeMein 0:67a55a82ce06 299 */
DeMein 0:67a55a82ce06 300 void spislirq::tx_addp(unsigned char c) {
DeMein 0:67a55a82ce06 301 // first empty buffer to at least 90%
DeMein 0:67a55a82ce06 302 switch (c) {
DeMein 0:67a55a82ce06 303 case c_arrow : tx_add(c_escape); // to send the > character
DeMein 0:67a55a82ce06 304 tx_add(c_arrow); // to send the > character
DeMein 0:67a55a82ce06 305 break;
DeMein 0:67a55a82ce06 306 case NULL : tx_add(c_escape); // to send the > character
DeMein 0:67a55a82ce06 307 tx_add(c_null); // to send the N character
DeMein 0:67a55a82ce06 308 break;
DeMein 0:67a55a82ce06 309 default : tx_add(c); // just send it ...
DeMein 0:67a55a82ce06 310 break;
DeMein 0:67a55a82ce06 311 }
DeMein 0:67a55a82ce06 312 }
DeMein 0:67a55a82ce06 313
DeMein 0:67a55a82ce06 314 /** adds a complete string to the transmit buffer, with protocol processing.
DeMein 0:67a55a82ce06 315 * function will block until there is room in the transmit buffer
DeMein 0:67a55a82ce06 316 *
DeMein 0:67a55a82ce06 317 * @param S string to be transmitted
DeMein 0:67a55a82ce06 318 * @return always returns 0
DeMein 0:67a55a82ce06 319 */
DeMein 0:67a55a82ce06 320 int spislirq::tx_string(char S[]) {
DeMein 0:67a55a82ce06 321 int i = 0;
DeMein 0:67a55a82ce06 322
DeMein 0:67a55a82ce06 323 while ((S[i] != 0x00)) {
DeMein 0:67a55a82ce06 324 // add until end of string
DeMein 0:67a55a82ce06 325 tx_addp(S[i]);
DeMein 0:67a55a82ce06 326 i++;
DeMein 0:67a55a82ce06 327 }
DeMein 0:67a55a82ce06 328 return(0);
DeMein 0:67a55a82ce06 329 }
DeMein 0:67a55a82ce06 330
DeMein 0:67a55a82ce06 331 /** inserts one byte in the receive buffer without protocol processing
DeMein 0:67a55a82ce06 332 * used for command batch processing
DeMein 0:67a55a82ce06 333 *
DeMein 0:67a55a82ce06 334 * @return the character read, blocks if RX buffer is empty!
DeMein 0:67a55a82ce06 335 *
DeMein 0:67a55a82ce06 336 */
DeMein 0:67a55a82ce06 337 int spislirq::rx_add(unsigned char c) {
DeMein 0:67a55a82ce06 338 while (rx_full()) {
DeMein 0:67a55a82ce06 339 do_callback();
DeMein 0:67a55a82ce06 340 wait_ms(1); // wait until RC buffer full
DeMein 0:67a55a82ce06 341 }
DeMein 0:67a55a82ce06 342 disable_irq();
DeMein 0:67a55a82ce06 343 if (!rx_full()) {
DeMein 0:67a55a82ce06 344 rxxbuf[rx_in] = c;
DeMein 0:67a55a82ce06 345 rx_in = (rx_in + 1) % bufsize;
DeMein 0:67a55a82ce06 346 enable_irq();
DeMein 0:67a55a82ce06 347 return c;
DeMein 0:67a55a82ce06 348 }
DeMein 0:67a55a82ce06 349 enable_irq();
DeMein 0:67a55a82ce06 350 return c;
DeMein 0:67a55a82ce06 351 }
DeMein 0:67a55a82ce06 352
DeMein 0:67a55a82ce06 353 /** read one byte from the receive buffer without protocol processing
DeMein 0:67a55a82ce06 354 *
DeMein 0:67a55a82ce06 355 * @return the character read, blocks if RX buffer is empty!
DeMein 0:67a55a82ce06 356 *
DeMein 0:67a55a82ce06 357 */
DeMein 0:67a55a82ce06 358 int spislirq::rx_read() {
DeMein 0:67a55a82ce06 359 unsigned char c = 0;
DeMein 0:67a55a82ce06 360
DeMein 0:67a55a82ce06 361 while (rx_empty()) {
DeMein 0:67a55a82ce06 362 do_callback();
DeMein 0:67a55a82ce06 363 wait_us(500);
DeMein 0:67a55a82ce06 364 }
DeMein 0:67a55a82ce06 365 disable_irq();
DeMein 0:67a55a82ce06 366 if (!rx_empty()) {
DeMein 0:67a55a82ce06 367 c = rxxbuf[rx_out];
DeMein 0:67a55a82ce06 368 rx_out = (rx_out + 1) % bufsize;
DeMein 0:67a55a82ce06 369 enable_irq();
DeMein 0:67a55a82ce06 370 // DBG_inchar(c);
DeMein 0:67a55a82ce06 371 return c;
DeMein 0:67a55a82ce06 372 }
DeMein 0:67a55a82ce06 373 enable_irq();
DeMein 0:67a55a82ce06 374 return c;
DeMein 0:67a55a82ce06 375 }
DeMein 0:67a55a82ce06 376
DeMein 0:67a55a82ce06 377 /** peeks in receive buffer, reads next pending input char without advancing buffer pointer
DeMein 0:67a55a82ce06 378 *
DeMein 0:67a55a82ce06 379 * @return the character read, blocks if RX buffer is empty!
DeMein 0:67a55a82ce06 380 *
DeMein 0:67a55a82ce06 381 */
DeMein 0:67a55a82ce06 382 int spislirq::rx_peek() {
DeMein 0:67a55a82ce06 383 unsigned char c = 0;
DeMein 0:67a55a82ce06 384
DeMein 0:67a55a82ce06 385 while (rx_empty()) {
DeMein 0:67a55a82ce06 386 do_callback();
DeMein 0:67a55a82ce06 387 wait_us(500);
DeMein 0:67a55a82ce06 388 }
DeMein 0:67a55a82ce06 389 disable_irq();
DeMein 0:67a55a82ce06 390 if (!rx_empty()) {
DeMein 0:67a55a82ce06 391 c = rxxbuf[rx_out];
DeMein 0:67a55a82ce06 392 }
DeMein 0:67a55a82ce06 393 enable_irq();
DeMein 0:67a55a82ce06 394 return c;
DeMein 0:67a55a82ce06 395 }
DeMein 0:67a55a82ce06 396
DeMein 0:67a55a82ce06 397 /** read one byte, will wait until a valid char is read,
DeMein 0:67a55a82ce06 398 * this function is blocking and will process escape characters,
DeMein 0:67a55a82ce06 399 * when an escape is seen, will try to read the next char
DeMein 0:67a55a82ce06 400 *
DeMein 0:67a55a82ce06 401 * @param mode command line processing or data read (ignored)
DeMein 0:67a55a82ce06 402 * @return character read, or -1 when >F seen, -2 when >I seen
DeMein 0:67a55a82ce06 403 *
DeMein 0:67a55a82ce06 404 */
DeMein 0:67a55a82ce06 405 int spislirq::rxx_read(bool mode) {
DeMein 0:67a55a82ce06 406 unsigned char bt1 = 0;
DeMein 0:67a55a82ce06 407 unsigned char bt2 = 0;
DeMein 0:67a55a82ce06 408 unsigned char h1 = 0;
DeMein 0:67a55a82ce06 409 unsigned char h2 = 0;
DeMein 0:67a55a82ce06 410 int rslt = 0;
DeMein 0:67a55a82ce06 411
DeMein 0:67a55a82ce06 412 bt1 = rx_read();
DeMein 0:67a55a82ce06 413
DeMein 0:67a55a82ce06 414 // we have now a character, check for escape codes
DeMein 0:67a55a82ce06 415 if (bt1 == c_escape) {
DeMein 0:67a55a82ce06 416 // this is an escape, now check for the next character
DeMein 0:67a55a82ce06 417 bt2 = rx_peek(); // peek in buffer, but do not read
DeMein 0:67a55a82ce06 418
DeMein 0:67a55a82ce06 419 switch (bt2) {
DeMein 0:67a55a82ce06 420 case c_arrow : bt2 = rx_read(); // read the char
DeMein 0:67a55a82ce06 421 rslt = c_escape;
DeMein 0:67a55a82ce06 422 break;
DeMein 0:67a55a82ce06 423
DeMein 0:67a55a82ce06 424 case c_eof : bt2 = rx_read(); // read the char
DeMein 0:67a55a82ce06 425 rslt = -1; // <EOF>
DeMein 0:67a55a82ce06 426 break;
DeMein 0:67a55a82ce06 427
DeMein 0:67a55a82ce06 428 case c_return : bt2 = rx_read(); // read the char
DeMein 0:67a55a82ce06 429 rslt = 0x0d; // carriage return
DeMein 0:67a55a82ce06 430 break;
DeMein 0:67a55a82ce06 431
DeMein 0:67a55a82ce06 432 case c_null :
DeMein 0:67a55a82ce06 433 case c_zero : bt2 = rx_read(); // read the char
DeMein 0:67a55a82ce06 434 rslt = 0; // zero char
DeMein 0:67a55a82ce06 435 break;
DeMein 0:67a55a82ce06 436
DeMein 0:67a55a82ce06 437 case c_hex :
DeMein 0:67a55a82ce06 438 case c_hexalt : bt2 = rx_read(); // read the char
DeMein 0:67a55a82ce06 439 // now get next two chars, which must be hex digits
DeMein 0:67a55a82ce06 440 h1 = rx_read(); // get data from buffer
DeMein 0:67a55a82ce06 441 h2 = rx_read(); // get data from buffer
DeMein 0:67a55a82ce06 442
DeMein 0:67a55a82ce06 443 rslt = 16 * hex2int(h1) + hex2int(h2); // calculate the result
DeMein 0:67a55a82ce06 444 break;
DeMein 0:67a55a82ce06 445
DeMein 0:67a55a82ce06 446 case c_intrpt : bt2 = rx_read(); // read the char
DeMein 0:67a55a82ce06 447 rslt = -2; // interrupt
DeMein 0:67a55a82ce06 448 break;
DeMein 0:67a55a82ce06 449
DeMein 0:67a55a82ce06 450 default : rslt = bt1; // ignore
DeMein 0:67a55a82ce06 451
DeMein 0:67a55a82ce06 452 } // end of switch(bt2)
DeMein 0:67a55a82ce06 453
DeMein 0:67a55a82ce06 454 } else {
DeMein 0:67a55a82ce06 455 // regular data send, no escape character
DeMein 0:67a55a82ce06 456 rslt = bt1;
DeMein 0:67a55a82ce06 457 }
DeMein 0:67a55a82ce06 458 return rslt;
DeMein 0:67a55a82ce06 459 }
DeMein 0:67a55a82ce06 460
DeMein 0:67a55a82ce06 461 void spislirq::DBG_set(int l) {
DeMein 0:67a55a82ce06 462 if ((l >= DBG_OFF) && (l <= DBG_FULL)) DBG_level = l;
DeMein 0:67a55a82ce06 463 }
DeMein 0:67a55a82ce06 464
DeMein 0:67a55a82ce06 465
DeMein 0:67a55a82ce06 466 /** show a debug message with a string and a character both a character and hex value
DeMein 0:67a55a82ce06 467 *
DeMein 0:67a55a82ce06 468 * @param src this will typically be the name of the function
DeMein 0:67a55a82ce06 469 * @param c character to be shown
DeMein 0:67a55a82ce06 470 */
DeMein 0:67a55a82ce06 471 void spislirq::DBG_chr(char* src, char c) {
DeMein 0:67a55a82ce06 472 if (DBG_level != DBG_OFF) {
DeMein 0:67a55a82ce06 473 int cc = c;
DeMein 0:67a55a82ce06 474 if (c < 32) c = '.';
DeMein 0:67a55a82ce06 475 printf("%s : %c [%02x]\n", src, c, cc);
DeMein 0:67a55a82ce06 476 }
DeMein 0:67a55a82ce06 477 }
DeMein 0:67a55a82ce06 478
DeMein 0:67a55a82ce06 479 /** show one character in hex, input from SPI to the MBED
DeMein 0:67a55a82ce06 480 *
DeMein 0:67a55a82ce06 481 * @param c input to be shown
DeMein 0:67a55a82ce06 482 */
DeMein 0:67a55a82ce06 483 void spislirq::DBG_inchar(char C) {
DeMein 0:67a55a82ce06 484 // prints only one char in hex, preceded by a + for input followed by a space
DeMein 0:67a55a82ce06 485 if (DBG_level == DBG_FULL) {
DeMein 0:67a55a82ce06 486 printf("+%02x ", C);
DeMein 0:67a55a82ce06 487 }
DeMein 0:67a55a82ce06 488 }
DeMein 0:67a55a82ce06 489
DeMein 0:67a55a82ce06 490 /** show one character in hex, output from MBED to SPI
DeMein 0:67a55a82ce06 491 *
DeMein 0:67a55a82ce06 492 * @param c output to be shown
DeMein 0:67a55a82ce06 493 */
DeMein 0:67a55a82ce06 494 void spislirq::DBG_outchar(char C) {
DeMein 0:67a55a82ce06 495 if (DBG_level == DBG_FULL) {
DeMein 0:67a55a82ce06 496 printf("-%02x ", C);
DeMein 0:67a55a82ce06 497 }
DeMein 0:67a55a82ce06 498 }
DeMein 0:67a55a82ce06 499
DeMein 0:67a55a82ce06 500 /** convert a hex char '0' to 'F' in its decimal equivalent
DeMein 0:67a55a82ce06 501 *
DeMein 0:67a55a82ce06 502 * @param C character
DeMein 0:67a55a82ce06 503 * @return a value 0 to 15, 0 when C was not in '0'..'F'
DeMein 0:67a55a82ce06 504 *
DeMein 0:67a55a82ce06 505 */
DeMein 0:67a55a82ce06 506 int spislirq::hex2int(char C) {
DeMein 0:67a55a82ce06 507 if ((C >= '0') && (C <= '9')) return(C - '0');
DeMein 0:67a55a82ce06 508 if ((C >= 'A') && (C <= 'F')) return(C - 'A' + 10);
DeMein 0:67a55a82ce06 509 return(0);
DeMein 0:67a55a82ce06 510 }