Prof Greg Egan
/
UAVXArm-GKE
UAVX Multicopter Flight Controller.
SerialBuffered.cpp@2:90292f8bd179, 2011-04-26 (annotated)
- Committer:
- gke
- Date:
- Tue Apr 26 12:12:29 2011 +0000
- Revision:
- 2:90292f8bd179
- Parent:
- 0:62a1c91a859a
Not flightworthy. Posted for others to make use of the I2C SW code.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gke | 0:62a1c91a859a | 1 | /* |
gke | 0:62a1c91a859a | 2 | Copyright (c) 2010 Andy Kirkham |
gke | 0:62a1c91a859a | 3 | |
gke | 0:62a1c91a859a | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy |
gke | 0:62a1c91a859a | 5 | of this software and associated documentation files (the "Software"), to deal |
gke | 0:62a1c91a859a | 6 | in the Software without restriction, including without limitation the rights |
gke | 0:62a1c91a859a | 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
gke | 0:62a1c91a859a | 8 | copies of the Software, and to permit persons to whom the Software is |
gke | 0:62a1c91a859a | 9 | furnished to do so, subject to the following conditions: |
gke | 0:62a1c91a859a | 10 | |
gke | 0:62a1c91a859a | 11 | The above copyright notice and this permission notice shall be included in |
gke | 0:62a1c91a859a | 12 | all copies or substantial portions of the Software. |
gke | 0:62a1c91a859a | 13 | |
gke | 0:62a1c91a859a | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
gke | 0:62a1c91a859a | 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
gke | 0:62a1c91a859a | 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
gke | 0:62a1c91a859a | 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
gke | 0:62a1c91a859a | 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
gke | 0:62a1c91a859a | 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
gke | 0:62a1c91a859a | 20 | THE SOFTWARE. |
gke | 0:62a1c91a859a | 21 | */ |
gke | 0:62a1c91a859a | 22 | |
gke | 0:62a1c91a859a | 23 | |
gke | 0:62a1c91a859a | 24 | #include "mbed.h" |
gke | 0:62a1c91a859a | 25 | |
gke | 0:62a1c91a859a | 26 | #ifndef SERIALBUFFERED_C |
gke | 0:62a1c91a859a | 27 | #define SERIALBUFFERED_C |
gke | 0:62a1c91a859a | 28 | #endif |
gke | 0:62a1c91a859a | 29 | |
gke | 0:62a1c91a859a | 30 | #include "SerialBuffered.h" |
gke | 0:62a1c91a859a | 31 | #include "sb_globals.h" |
gke | 0:62a1c91a859a | 32 | |
gke | 0:62a1c91a859a | 33 | enum { None, One, Two }; |
gke | 0:62a1c91a859a | 34 | enum { WordLength5, WordLength6, WordLength7, WordLength8 }; |
gke | 0:62a1c91a859a | 35 | enum { NoParity, OddParity, EvenParity, Forced1, Forced0 }; |
gke | 0:62a1c91a859a | 36 | enum { StopBit1, StopBit2 }; |
gke | 0:62a1c91a859a | 37 | |
gke | 0:62a1c91a859a | 38 | SerialBuffered::SerialBuffered(PinName tx, PinName rx) : Serial(tx, rx) { |
gke | 0:62a1c91a859a | 39 | |
gke | 0:62a1c91a859a | 40 | // Depending upon the pins used, set-up the Uart. |
gke | 0:62a1c91a859a | 41 | if (tx == p9 || rx == p10) { |
gke | 0:62a1c91a859a | 42 | uart_number = 3; |
gke | 0:62a1c91a859a | 43 | uart_base = LPC_UART3_BASE; |
gke | 0:62a1c91a859a | 44 | set_uart3(tx, rx); |
gke | 0:62a1c91a859a | 45 | } |
gke | 0:62a1c91a859a | 46 | else if (tx == p13 || tx == p26 || rx == p14 || rx == p25) { |
gke | 0:62a1c91a859a | 47 | uart_number = 1; |
gke | 0:62a1c91a859a | 48 | uart_base = LPC_UART1_BASE; |
gke | 0:62a1c91a859a | 49 | set_uart1(tx, rx); |
gke | 0:62a1c91a859a | 50 | } |
gke | 0:62a1c91a859a | 51 | else if (tx == p28 || rx == p27) { |
gke | 0:62a1c91a859a | 52 | uart_number = 2; |
gke | 0:62a1c91a859a | 53 | uart_base = LPC_UART2_BASE; |
gke | 0:62a1c91a859a | 54 | set_uart2(tx, rx); |
gke | 0:62a1c91a859a | 55 | } |
gke | 0:62a1c91a859a | 56 | else if (tx == USBTX || rx == USBRX) { |
gke | 0:62a1c91a859a | 57 | uart_number = 0; |
gke | 0:62a1c91a859a | 58 | uart_base = LPC_UART0_BASE; |
gke | 0:62a1c91a859a | 59 | set_uart0(tx, rx); |
gke | 0:62a1c91a859a | 60 | } |
gke | 0:62a1c91a859a | 61 | else { |
gke | 0:62a1c91a859a | 62 | uart_number = -1; |
gke | 0:62a1c91a859a | 63 | return; |
gke | 0:62a1c91a859a | 64 | } |
gke | 0:62a1c91a859a | 65 | } |
gke | 0:62a1c91a859a | 66 | |
gke | 0:62a1c91a859a | 67 | SerialBuffered::~SerialBuffered() { |
gke | 0:62a1c91a859a | 68 | if (_tx_buffer_used_malloc[uart_number] && _tx_buffer[uart_number]) free(_tx_buffer[uart_number]); |
gke | 0:62a1c91a859a | 69 | if (_rx_buffer_used_malloc[uart_number] && _rx_buffer[uart_number]) free(_rx_buffer[uart_number]); |
gke | 0:62a1c91a859a | 70 | } |
gke | 0:62a1c91a859a | 71 | |
gke | 0:62a1c91a859a | 72 | /** SerialBuffered_ISR |
gke | 0:62a1c91a859a | 73 | * |
gke | 0:62a1c91a859a | 74 | * The main Uart interrupt handler. |
gke | 0:62a1c91a859a | 75 | */ |
gke | 0:62a1c91a859a | 76 | extern "C" void SerialBuffered_ISR(unsigned long uart_base, int uart_number) { |
gke | 0:62a1c91a859a | 77 | char c __attribute__((unused)); |
gke | 0:62a1c91a859a | 78 | volatile uint32_t iir, lsr; |
gke | 0:62a1c91a859a | 79 | |
gke | 0:62a1c91a859a | 80 | iir = GET_REGISTER(SERIALBUFFERED_IIR); |
gke | 0:62a1c91a859a | 81 | |
gke | 0:62a1c91a859a | 82 | if (iir & 1) { |
gke | 0:62a1c91a859a | 83 | return; /* Eh, wtf? */ |
gke | 0:62a1c91a859a | 84 | } |
gke | 0:62a1c91a859a | 85 | |
gke | 0:62a1c91a859a | 86 | iir = (iir >> 1) & 0x3; |
gke | 0:62a1c91a859a | 87 | |
gke | 0:62a1c91a859a | 88 | if (iir == 2) { |
gke | 0:62a1c91a859a | 89 | while(GET_REGISTER(SERIALBUFFERED_LSR) & 0x1) { |
gke | 0:62a1c91a859a | 90 | if (_rx_buffer_in[uart_number] == _rx_buffer_out[uart_number] && _rx_buffer_full[uart_number]) { |
gke | 0:62a1c91a859a | 91 | c = GET_REGISTER(SERIALBUFFERED_RBR); /* Oh dear, we need a bigger buffer!, send to dev/null */ |
gke | 0:62a1c91a859a | 92 | _rx_buffer_overflow[uart_number] = true; |
gke | 0:62a1c91a859a | 93 | } |
gke | 0:62a1c91a859a | 94 | else { |
gke | 0:62a1c91a859a | 95 | if (_rx_buffer[uart_number]) { /* Ensure buffer pointer is not null before use. */ |
gke | 0:62a1c91a859a | 96 | c = GET_REGISTER(SERIALBUFFERED_RBR); |
gke | 0:62a1c91a859a | 97 | _rx_buffer[uart_number][_rx_buffer_in[uart_number]++] = c; |
gke | 0:62a1c91a859a | 98 | if (_rx_buffer_in[uart_number] >= _rx_buffer_size[uart_number]) _rx_buffer_in[uart_number] = 0; |
gke | 0:62a1c91a859a | 99 | if (_rx_buffer_in[uart_number] == _rx_buffer_out[uart_number]) _rx_buffer_full[uart_number] = true; |
gke | 0:62a1c91a859a | 100 | } |
gke | 0:62a1c91a859a | 101 | } |
gke | 0:62a1c91a859a | 102 | } |
gke | 0:62a1c91a859a | 103 | } |
gke | 0:62a1c91a859a | 104 | |
gke | 0:62a1c91a859a | 105 | if (iir == 1) { |
gke | 0:62a1c91a859a | 106 | if (_tx_buffer[uart_number]) { /* Ensure buffer pointer is not null before use. */ |
gke | 0:62a1c91a859a | 107 | if (_tx_buffer_in[uart_number] != _tx_buffer_out[uart_number] || _tx_buffer_full[uart_number]) { |
gke | 0:62a1c91a859a | 108 | SET_REGISTER(SERIALBUFFERED_THR, (uint32_t)(_tx_buffer[uart_number][_tx_buffer_out[uart_number]++])); |
gke | 0:62a1c91a859a | 109 | if (_tx_buffer_out[uart_number] >= _tx_buffer_size[uart_number]) _tx_buffer_out[uart_number] = 0; |
gke | 0:62a1c91a859a | 110 | _tx_buffer_full[uart_number] = false; |
gke | 0:62a1c91a859a | 111 | } |
gke | 0:62a1c91a859a | 112 | else { |
gke | 0:62a1c91a859a | 113 | SET_REGISTER(SERIALBUFFERED_IER, 1); |
gke | 0:62a1c91a859a | 114 | } |
gke | 0:62a1c91a859a | 115 | } |
gke | 0:62a1c91a859a | 116 | } |
gke | 0:62a1c91a859a | 117 | |
gke | 0:62a1c91a859a | 118 | if (iir == 3) { |
gke | 0:62a1c91a859a | 119 | /* We need to provide an error handling system. For now, just dismiss the IRQ. */ |
gke | 0:62a1c91a859a | 120 | lsr = GET_REGISTER(SERIALBUFFERED_LSR); |
gke | 0:62a1c91a859a | 121 | } |
gke | 0:62a1c91a859a | 122 | } |
gke | 0:62a1c91a859a | 123 |