Mark Gottscho / UtilityLib

Fork of UtilityLib by Mark Gottscho

Committer:
mgottscho
Date:
Tue Mar 18 23:56:23 2014 +0000
Revision:
9:f71dc1b426da
Made the Utility class just a SerialManager, and factored out useful functionality not relevant to serial operation into global C functions.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mgottscho 9:f71dc1b426da 1 /* SerialManager.cpp
mgottscho 9:f71dc1b426da 2 * Tested with mbed board: FRDM-KL46Z
mgottscho 9:f71dc1b426da 3 * Author: Mark Gottscho
mgottscho 9:f71dc1b426da 4 * mgottscho@ucla.edu
mgottscho 9:f71dc1b426da 5 */
mgottscho 9:f71dc1b426da 6
mgottscho 9:f71dc1b426da 7 #include "mbed.h"
mgottscho 9:f71dc1b426da 8 #include "SerialManager.h"
mgottscho 9:f71dc1b426da 9
mgottscho 9:f71dc1b426da 10 using namespace std;
mgottscho 9:f71dc1b426da 11
mgottscho 9:f71dc1b426da 12 SerialManager::SerialManager(PinName serial_tx_pin, PinName serial_rx_pin, int baudrate, bool enableSerialInterrupts) :
mgottscho 9:f71dc1b426da 13 serial(serial_tx_pin, serial_rx_pin),
mgottscho 9:f71dc1b426da 14 __interrupts_en(enableSerialInterrupts),
mgottscho 9:f71dc1b426da 15 __user_fptr(NULL),
mgottscho 9:f71dc1b426da 16 __rx_head(0),
mgottscho 9:f71dc1b426da 17 __rx_tail(0),
mgottscho 9:f71dc1b426da 18 __tx_head(0),
mgottscho 9:f71dc1b426da 19 __tx_tail(0),
mgottscho 9:f71dc1b426da 20 __have_rx_serial(false)
mgottscho 9:f71dc1b426da 21 {
mgottscho 9:f71dc1b426da 22
mgottscho 9:f71dc1b426da 23 serial.baud(baudrate);
mgottscho 9:f71dc1b426da 24
mgottscho 9:f71dc1b426da 25 //Set up serial interrupt handlers
mgottscho 9:f71dc1b426da 26 if (__interrupts_en) {
mgottscho 9:f71dc1b426da 27 serial.attach(this, &SerialManager::__serial_rx_ISR, Serial::RxIrq);
mgottscho 9:f71dc1b426da 28 //serial.attach(this, &SerialManager::__serial_tx_ISR, Serial::TxIrq);
mgottscho 9:f71dc1b426da 29 }
mgottscho 9:f71dc1b426da 30 }
mgottscho 9:f71dc1b426da 31
mgottscho 9:f71dc1b426da 32 SerialManager::~SerialManager() {
mgottscho 9:f71dc1b426da 33 detach_rx();
mgottscho 9:f71dc1b426da 34 }
mgottscho 9:f71dc1b426da 35
mgottscho 9:f71dc1b426da 36 void SerialManager::attach_rx(void (*fptr)(void)) {
mgottscho 9:f71dc1b426da 37 //set user function pointer
mgottscho 9:f71dc1b426da 38 detach_rx();
mgottscho 9:f71dc1b426da 39 if (fptr != NULL)
mgottscho 9:f71dc1b426da 40 __user_fptr = new FunctionPointer(fptr);
mgottscho 9:f71dc1b426da 41 }
mgottscho 9:f71dc1b426da 42
mgottscho 9:f71dc1b426da 43 template<typename T> void SerialManager::attach_rx(T *tptr, void (T::*mptr)(void)) {
mgottscho 9:f71dc1b426da 44 //set user function pointer
mgottscho 9:f71dc1b426da 45 detach();
mgottscho 9:f71dc1b426da 46 if (tptr != NULL && mptr != NULL)
mgottscho 9:f71dc1b426da 47 __user_fptr = new FunctionPointer(tptr, mptr);
mgottscho 9:f71dc1b426da 48 }
mgottscho 9:f71dc1b426da 49
mgottscho 9:f71dc1b426da 50 void SerialManager::detach_rx() {
mgottscho 9:f71dc1b426da 51 if (__user_fptr != NULL)
mgottscho 9:f71dc1b426da 52 delete __user_fptr;
mgottscho 9:f71dc1b426da 53 __user_fptr = NULL;
mgottscho 9:f71dc1b426da 54 }
mgottscho 9:f71dc1b426da 55
mgottscho 9:f71dc1b426da 56 //THIS DOES NOT WORK YET
mgottscho 9:f71dc1b426da 57 /*uint32_t SerialManager::sendLine(const char *line, const uint32_t len) {
mgottscho 9:f71dc1b426da 58 int i = 0;
mgottscho 9:f71dc1b426da 59 char temp_byte;
mgottscho 9:f71dc1b426da 60 bool buf_empty;
mgottscho 9:f71dc1b426da 61
mgottscho 9:f71dc1b426da 62 if (line == NULL) //check input
mgottscho 9:f71dc1b426da 63 return 0;
mgottscho 9:f71dc1b426da 64
mgottscho 9:f71dc1b426da 65 G_red_led = 0;
mgottscho 9:f71dc1b426da 66
mgottscho 9:f71dc1b426da 67 // Start critical section - don't interrupt while changing global buffer variables
mgottscho 9:f71dc1b426da 68 __disable_irq();
mgottscho 9:f71dc1b426da 69 buf_empty = (G_tx_head == G_tx_tail);
mgottscho 9:f71dc1b426da 70
mgottscho 9:f71dc1b426da 71 while (i < len && line[i] != '\r') { //Loop until we have sent the maximum number of characters or we hit a carriage return
mgottscho 9:f71dc1b426da 72 // Wait if tx buffer full
mgottscho 9:f71dc1b426da 73 if ((G_tx_head + 1) % BUFFER_SIZE == G_tx_tail) { //If TX buffer is full, wait.
mgottscho 9:f71dc1b426da 74 // End critical section - need to let interrupt routine empty buffer by sending
mgottscho 9:f71dc1b426da 75 __enable_irq();
mgottscho 9:f71dc1b426da 76 while ((G_tx_head + 1) % BUFFER_SIZE == G_tx_tail) { } //Spinloop until TX buffer is not full
mgottscho 9:f71dc1b426da 77 // Start critical section - don't interrupt while changing global buffer variables
mgottscho 9:f71dc1b426da 78 __disable_irq();
mgottscho 9:f71dc1b426da 79 }
mgottscho 9:f71dc1b426da 80 G_tx_head = (G_tx_head + 1) % BUFFER_SIZE;
mgottscho 9:f71dc1b426da 81 G_tx_buf[G_tx_head] = line[i++];
mgottscho 9:f71dc1b426da 82 }
mgottscho 9:f71dc1b426da 83
mgottscho 9:f71dc1b426da 84 //Now we have buffered all characters in the line. Trigger the TX serial interrupt
mgottscho 9:f71dc1b426da 85 if (G_console.writeable() && buf_empty) {
mgottscho 9:f71dc1b426da 86 //Write the first byte to get it started
mgottscho 9:f71dc1b426da 87 temp_byte = G_tx_buf[G_tx_tail];
mgottscho 9:f71dc1b426da 88 G_tx_tail = (G_tx_tail + 1) % BUFFER_SIZE;
mgottscho 9:f71dc1b426da 89
mgottscho 9:f71dc1b426da 90 // Send first character to start tx interrupts, if stopped
mgottscho 9:f71dc1b426da 91 G_console.putc(temp_byte);
mgottscho 9:f71dc1b426da 92 }
mgottscho 9:f71dc1b426da 93
mgottscho 9:f71dc1b426da 94 // End critical section
mgottscho 9:f71dc1b426da 95 __enable_irq();
mgottscho 9:f71dc1b426da 96
mgottscho 9:f71dc1b426da 97 G_red_led = 1;
mgottscho 9:f71dc1b426da 98
mgottscho 9:f71dc1b426da 99 return i;
mgottscho 9:f71dc1b426da 100 }*/
mgottscho 9:f71dc1b426da 101
mgottscho 9:f71dc1b426da 102
mgottscho 9:f71dc1b426da 103 uint32_t SerialManager::receiveLine(char *line, const uint32_t len) {
mgottscho 9:f71dc1b426da 104 int i = 0;
mgottscho 9:f71dc1b426da 105 char lastChar = '\0';
mgottscho 9:f71dc1b426da 106
mgottscho 9:f71dc1b426da 107 if (line == NULL) //check input
mgottscho 9:f71dc1b426da 108 return 0;
mgottscho 9:f71dc1b426da 109
mgottscho 9:f71dc1b426da 110 // Start critical section - don't interrupt while changing global buffer variables
mgottscho 9:f71dc1b426da 111 __disable_uart_irq();
mgottscho 9:f71dc1b426da 112
mgottscho 9:f71dc1b426da 113 while (i < len && lastChar != '\r') { //Loop until maximum number of characters or a newline symbol
mgottscho 9:f71dc1b426da 114 //Wait for more characters if the rx buffer is empty
mgottscho 9:f71dc1b426da 115 if (__rx_tail == __rx_head) {
mgottscho 9:f71dc1b426da 116 // End critical section - need to allow rx interrupt to get new characters for buffer
mgottscho 9:f71dc1b426da 117 __enable_uart_irq();
mgottscho 9:f71dc1b426da 118 while (__rx_tail == __rx_head) { } //Spinloop until there are some characters
mgottscho 9:f71dc1b426da 119 // Start critical section - don't interrupt while changing global buffer variables
mgottscho 9:f71dc1b426da 120 __disable_uart_irq();
mgottscho 9:f71dc1b426da 121 }
mgottscho 9:f71dc1b426da 122
mgottscho 9:f71dc1b426da 123 lastChar = __rx_buf[__rx_tail];
mgottscho 9:f71dc1b426da 124 if (lastChar == '\r') //newline symbol
mgottscho 9:f71dc1b426da 125 line[i] = '\0';
mgottscho 9:f71dc1b426da 126 else
mgottscho 9:f71dc1b426da 127 line[i] = lastChar;
mgottscho 9:f71dc1b426da 128 i++;
mgottscho 9:f71dc1b426da 129 __rx_tail = (__rx_tail + 1) % BUFFER_SIZE;
mgottscho 9:f71dc1b426da 130 }
mgottscho 9:f71dc1b426da 131
mgottscho 9:f71dc1b426da 132 //Clear flag
mgottscho 9:f71dc1b426da 133 __have_rx_serial = false;
mgottscho 9:f71dc1b426da 134
mgottscho 9:f71dc1b426da 135 // End critical section
mgottscho 9:f71dc1b426da 136 __enable_uart_irq();
mgottscho 9:f71dc1b426da 137
mgottscho 9:f71dc1b426da 138 return i;
mgottscho 9:f71dc1b426da 139 }
mgottscho 9:f71dc1b426da 140
mgottscho 9:f71dc1b426da 141 bool SerialManager::haveRxSerialData() {
mgottscho 9:f71dc1b426da 142 return __have_rx_serial;
mgottscho 9:f71dc1b426da 143 }
mgottscho 9:f71dc1b426da 144
mgottscho 9:f71dc1b426da 145 void SerialManager::flush() {
mgottscho 9:f71dc1b426da 146 while (serial.readable()) {
mgottscho 9:f71dc1b426da 147 serial.getc();
mgottscho 9:f71dc1b426da 148 }
mgottscho 9:f71dc1b426da 149 }
mgottscho 9:f71dc1b426da 150
mgottscho 9:f71dc1b426da 151 void SerialManager::print_line(const char *line, int len) {
mgottscho 9:f71dc1b426da 152 if (line == NULL || len < 1)
mgottscho 9:f71dc1b426da 153 return;
mgottscho 9:f71dc1b426da 154
mgottscho 9:f71dc1b426da 155 const char *curr = line;
mgottscho 9:f71dc1b426da 156 while (curr < line+len && *curr != '\0') {
mgottscho 9:f71dc1b426da 157 serial.putc(*curr);
mgottscho 9:f71dc1b426da 158 curr++;
mgottscho 9:f71dc1b426da 159 }
mgottscho 9:f71dc1b426da 160 }
mgottscho 9:f71dc1b426da 161
mgottscho 9:f71dc1b426da 162 void SerialManager::__serial_rx_ISR() {
mgottscho 9:f71dc1b426da 163 char tmp;
mgottscho 9:f71dc1b426da 164
mgottscho 9:f71dc1b426da 165 if (__user_fptr != NULL) //user callback
mgottscho 9:f71dc1b426da 166 __user_fptr->call();
mgottscho 9:f71dc1b426da 167
mgottscho 9:f71dc1b426da 168 //Loop while the UART inbound FIFO is not empty and the receiving buffer is not full
mgottscho 9:f71dc1b426da 169 while (serial.readable() && (__rx_head != (__rx_tail - 1) % BUFFER_SIZE)) {
mgottscho 9:f71dc1b426da 170 tmp = serial.getc(); //read a byte into the buffer from the serial port
mgottscho 9:f71dc1b426da 171 __rx_buf[__rx_head] = tmp;
mgottscho 9:f71dc1b426da 172 __rx_head = (__rx_head + 1) % BUFFER_SIZE;
mgottscho 9:f71dc1b426da 173 if (tmp == '\r')
mgottscho 9:f71dc1b426da 174 __have_rx_serial = true;
mgottscho 9:f71dc1b426da 175 }
mgottscho 9:f71dc1b426da 176 }
mgottscho 9:f71dc1b426da 177
mgottscho 9:f71dc1b426da 178 //THIS DOES NOT WORK YET
mgottscho 9:f71dc1b426da 179 /*void SerialManager::__serial_tx_ISR() {
mgottscho 9:f71dc1b426da 180 //Loop while the UART outbound FIFO is not full and the transmitting buffer is not empty
mgottscho 9:f71dc1b426da 181 while (G_console.writeable() && (G_tx_tail != G_tx_head)) {
mgottscho 9:f71dc1b426da 182 G_console.putc(G_tx_buf[G_tx_tail]); //write a byte to the serial port from the buffer
mgottscho 9:f71dc1b426da 183 G_tx_tail = (G_tx_tail + 1) % BUFFER_SIZE;
mgottscho 9:f71dc1b426da 184 }
mgottscho 9:f71dc1b426da 185 }*/
mgottscho 9:f71dc1b426da 186
mgottscho 9:f71dc1b426da 187 inline void SerialManager::__disable_uart_irq() {
mgottscho 9:f71dc1b426da 188 // Start critical section - don't interrupt with serial I/O
mgottscho 9:f71dc1b426da 189 // Since user specifies UART TX/RX pins, we don't know which we are using, so disable all 3
mgottscho 9:f71dc1b426da 190 NVIC_DisableIRQ(UART0_IRQn);
mgottscho 9:f71dc1b426da 191 NVIC_DisableIRQ(UART1_IRQn);
mgottscho 9:f71dc1b426da 192 NVIC_DisableIRQ(UART2_IRQn);
mgottscho 9:f71dc1b426da 193 }
mgottscho 9:f71dc1b426da 194
mgottscho 9:f71dc1b426da 195 inline void SerialManager::__enable_uart_irq() {
mgottscho 9:f71dc1b426da 196 // End critical section - can now interrupt with serial I/O
mgottscho 9:f71dc1b426da 197 // Since user specifies UART TX/RX pins, we don't know which we are using, so enable all 3
mgottscho 9:f71dc1b426da 198 NVIC_EnableIRQ(UART0_IRQn);
mgottscho 9:f71dc1b426da 199 NVIC_EnableIRQ(UART1_IRQn);
mgottscho 9:f71dc1b426da 200 NVIC_EnableIRQ(UART2_IRQn);
mgottscho 9:f71dc1b426da 201 }