Mark Gottscho / UtilityLib

Fork of UtilityLib by Mark Gottscho

Committer:
mgottscho
Date:
Tue Mar 11 21:13:48 2014 +0000
Revision:
4:28f50e540872
Parent:
3:87ce0325374d
Child:
5:9cd633b79b23
Fixes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mgottscho 0:cc61e9d1c295 1 /* Utility.cpp
mgottscho 0:cc61e9d1c295 2 * Tested with mbed board: FRDM-KL46Z
mgottscho 0:cc61e9d1c295 3 * Author: Mark Gottscho
mgottscho 0:cc61e9d1c295 4 * mgottscho@ucla.edu
mgottscho 0:cc61e9d1c295 5 */
mgottscho 0:cc61e9d1c295 6
mgottscho 0:cc61e9d1c295 7 #include "mbed.h"
mgottscho 0:cc61e9d1c295 8 #include <string>
mgottscho 0:cc61e9d1c295 9 #include "Utility.h"
mgottscho 0:cc61e9d1c295 10
mgottscho 0:cc61e9d1c295 11 using namespace std;
mgottscho 0:cc61e9d1c295 12
mgottscho 3:87ce0325374d 13 Utility::Utility(PinName green_led_pin, PinName red_led_pin, PinName serial_tx_pin, PinName serial_rx_pin, int baudrate, bool enableSerialInterrupts) :
mgottscho 0:cc61e9d1c295 14 console(serial_tx_pin, serial_rx_pin),
mgottscho 3:87ce0325374d 15 green_led(green_led_pin),
mgottscho 3:87ce0325374d 16 red_led(red_led_pin),
mgottscho 3:87ce0325374d 17 __interrupts_en(enableSerialInterrupts),
mgottscho 3:87ce0325374d 18 __user_fptr(NULL),
mgottscho 0:cc61e9d1c295 19 __green_led_interrupt(),
mgottscho 1:2a3bbec22035 20 __red_led_interrupt(),
mgottscho 1:2a3bbec22035 21 __rx_head(0),
mgottscho 1:2a3bbec22035 22 __rx_tail(0),
mgottscho 1:2a3bbec22035 23 __tx_head(0),
mgottscho 1:2a3bbec22035 24 __tx_tail(0),
mgottscho 2:3e09d74e5cf0 25 __have_rx_serial(false)
mgottscho 2:3e09d74e5cf0 26 {
mgottscho 1:2a3bbec22035 27
mgottscho 3:87ce0325374d 28 red_led = 1;
mgottscho 3:87ce0325374d 29 green_led = 1;
mgottscho 1:2a3bbec22035 30
mgottscho 3:87ce0325374d 31 console.baud(baudrate); //115200, 230400 confirmed to work, above this seems to fail
mgottscho 1:2a3bbec22035 32
mgottscho 1:2a3bbec22035 33 //Set up serial interrupt handlers
mgottscho 3:87ce0325374d 34 if (__interrupts_en) {
mgottscho 2:3e09d74e5cf0 35 console.attach(this, &Utility::__console_rx_ISR, Serial::RxIrq);
mgottscho 2:3e09d74e5cf0 36 //console.attach(this, &Utility::__console_tx_ISR, Serial::TxIrq);
mgottscho 2:3e09d74e5cf0 37 }
mgottscho 0:cc61e9d1c295 38 }
mgottscho 0:cc61e9d1c295 39
mgottscho 3:87ce0325374d 40 Utility::~Utility() {
mgottscho 3:87ce0325374d 41 detach();
mgottscho 3:87ce0325374d 42 }
mgottscho 3:87ce0325374d 43
mgottscho 3:87ce0325374d 44 void Utility::attach(void (*fptr)(void)) {
mgottscho 3:87ce0325374d 45 //set user function pointer
mgottscho 3:87ce0325374d 46 detach();
mgottscho 3:87ce0325374d 47 if (fptr != NULL)
mgottscho 3:87ce0325374d 48 __user_fptr = new FunctionPointer(fptr);
mgottscho 3:87ce0325374d 49 }
mgottscho 0:cc61e9d1c295 50
mgottscho 3:87ce0325374d 51 template<typename T> void Utility::attach(T *tptr, void (T::*mptr)(void)) {
mgottscho 3:87ce0325374d 52 //set user function pointer
mgottscho 3:87ce0325374d 53 detach();
mgottscho 3:87ce0325374d 54 if (tptr != NULL && mptr != NULL)
mgottscho 3:87ce0325374d 55 __user_fptr = new FunctionPointer(tptr, mptr);
mgottscho 3:87ce0325374d 56 }
mgottscho 3:87ce0325374d 57
mgottscho 3:87ce0325374d 58 void Utility::detach() {
mgottscho 3:87ce0325374d 59 if (__user_fptr != NULL)
mgottscho 3:87ce0325374d 60 delete __user_fptr;
mgottscho 3:87ce0325374d 61 __user_fptr = NULL;
mgottscho 3:87ce0325374d 62 }
mgottscho 0:cc61e9d1c295 63
mgottscho 0:cc61e9d1c295 64 void Utility::panic(string errorMessage, int errorCode) {
mgottscho 0:cc61e9d1c295 65 //We're dead. This is the point of no return! Permanently ignore interrupts.
mgottscho 0:cc61e9d1c295 66 __disable_irq();
mgottscho 0:cc61e9d1c295 67
mgottscho 2:3e09d74e5cf0 68 console.printf(">>> PANIC, CODE # %d: %s <<<\r\n", errorCode, errorMessage.c_str());
mgottscho 0:cc61e9d1c295 69
mgottscho 3:87ce0325374d 70 green_led = 1;
mgottscho 3:87ce0325374d 71 red_led = 0;
mgottscho 0:cc61e9d1c295 72
mgottscho 0:cc61e9d1c295 73 volatile uint32_t fake = 0;
mgottscho 0:cc61e9d1c295 74 while(1) { fake = 0; } //Spinloop for eternity
mgottscho 0:cc61e9d1c295 75 }
mgottscho 0:cc61e9d1c295 76
mgottscho 0:cc61e9d1c295 77 void Utility::warn(string errorMessage, int errorCode) {
mgottscho 2:3e09d74e5cf0 78 console.printf(">>> WARN, CODE # %d: %s <<<\r\n", errorCode, errorMessage.c_str());
mgottscho 0:cc61e9d1c295 79 }
mgottscho 0:cc61e9d1c295 80
mgottscho 0:cc61e9d1c295 81 #ifdef NDEBUG
mgottscho 0:cc61e9d1c295 82 void Utility::myAssert(bool condition, const char *file, const unsigned long line) { }
mgottscho 0:cc61e9d1c295 83 #else
mgottscho 0:cc61e9d1c295 84 void Utility::myAssert(bool condition, const char *file, const unsigned long line) {
mgottscho 0:cc61e9d1c295 85 if (!condition)
mgottscho 0:cc61e9d1c295 86 {
mgottscho 0:cc61e9d1c295 87 char msg[256];
mgottscho 0:cc61e9d1c295 88 sprintf(msg, "Assertion failed at file %s, line %d", file, line);
mgottscho 0:cc61e9d1c295 89 panic(msg, -1); \
mgottscho 0:cc61e9d1c295 90 }
mgottscho 0:cc61e9d1c295 91 }
mgottscho 0:cc61e9d1c295 92 #endif
mgottscho 0:cc61e9d1c295 93
mgottscho 0:cc61e9d1c295 94 void Utility::blinkGreen(bool enable, float half_period) {
mgottscho 0:cc61e9d1c295 95 if (enable) {
mgottscho 3:87ce0325374d 96 if (half_period <= 0.01) {
mgottscho 0:cc61e9d1c295 97 __green_led_interrupt.detach();
mgottscho 3:87ce0325374d 98 green_led = 0;
mgottscho 0:cc61e9d1c295 99 } else if (half_period <= 1800)
mgottscho 0:cc61e9d1c295 100 __green_led_interrupt.attach(this, &Utility::__greenLED_ISR, half_period);
mgottscho 0:cc61e9d1c295 101 }
mgottscho 0:cc61e9d1c295 102 else {
mgottscho 0:cc61e9d1c295 103 __green_led_interrupt.detach();
mgottscho 3:87ce0325374d 104 green_led = 1;
mgottscho 0:cc61e9d1c295 105 }
mgottscho 0:cc61e9d1c295 106 }
mgottscho 0:cc61e9d1c295 107
mgottscho 0:cc61e9d1c295 108 void Utility::blinkRed(bool enable, float half_period) {
mgottscho 0:cc61e9d1c295 109 if (enable) {
mgottscho 3:87ce0325374d 110 if (half_period <= 0.01) {
mgottscho 0:cc61e9d1c295 111 __red_led_interrupt.detach();
mgottscho 3:87ce0325374d 112 red_led = 0;
mgottscho 0:cc61e9d1c295 113 } else if (half_period <= 1800)
mgottscho 0:cc61e9d1c295 114 __red_led_interrupt.attach(this, &Utility::__redLED_ISR, half_period);
mgottscho 0:cc61e9d1c295 115 }
mgottscho 0:cc61e9d1c295 116 else {
mgottscho 0:cc61e9d1c295 117 __red_led_interrupt.detach();
mgottscho 3:87ce0325374d 118 red_led = 1;
mgottscho 0:cc61e9d1c295 119 }
mgottscho 0:cc61e9d1c295 120 }
mgottscho 0:cc61e9d1c295 121
mgottscho 1:2a3bbec22035 122 //THIS DOES NOT WORK YET
mgottscho 1:2a3bbec22035 123 /*uint32_t Utility::sendLine(const char *line, const uint32_t len) {
mgottscho 1:2a3bbec22035 124 int i = 0;
mgottscho 1:2a3bbec22035 125 char temp_byte;
mgottscho 1:2a3bbec22035 126 bool buf_empty;
mgottscho 1:2a3bbec22035 127
mgottscho 1:2a3bbec22035 128 if (line == NULL) //check input
mgottscho 1:2a3bbec22035 129 return 0;
mgottscho 1:2a3bbec22035 130
mgottscho 1:2a3bbec22035 131 G_red_led = 0;
mgottscho 1:2a3bbec22035 132
mgottscho 1:2a3bbec22035 133 // Start critical section - don't interrupt while changing global buffer variables
mgottscho 1:2a3bbec22035 134 __disable_irq();
mgottscho 1:2a3bbec22035 135 buf_empty = (G_tx_head == G_tx_tail);
mgottscho 1:2a3bbec22035 136
mgottscho 1:2a3bbec22035 137 while (i < len && line[i] != '\r') { //Loop until we have sent the maximum number of characters or we hit a carriage return
mgottscho 1:2a3bbec22035 138 // Wait if tx buffer full
mgottscho 1:2a3bbec22035 139 if ((G_tx_head + 1) % BUFFER_SIZE == G_tx_tail) { //If TX buffer is full, wait.
mgottscho 1:2a3bbec22035 140 // End critical section - need to let interrupt routine empty buffer by sending
mgottscho 1:2a3bbec22035 141 __enable_irq();
mgottscho 1:2a3bbec22035 142 while ((G_tx_head + 1) % BUFFER_SIZE == G_tx_tail) { } //Spinloop until TX buffer is not full
mgottscho 1:2a3bbec22035 143 // Start critical section - don't interrupt while changing global buffer variables
mgottscho 1:2a3bbec22035 144 __disable_irq();
mgottscho 1:2a3bbec22035 145 }
mgottscho 1:2a3bbec22035 146 G_tx_head = (G_tx_head + 1) % BUFFER_SIZE;
mgottscho 1:2a3bbec22035 147 G_tx_buf[G_tx_head] = line[i++];
mgottscho 1:2a3bbec22035 148 }
mgottscho 1:2a3bbec22035 149
mgottscho 1:2a3bbec22035 150 //Now we have buffered all characters in the line. Trigger the TX serial interrupt
mgottscho 1:2a3bbec22035 151 if (G_console.writeable() && buf_empty) {
mgottscho 1:2a3bbec22035 152 //Write the first byte to get it started
mgottscho 1:2a3bbec22035 153 temp_byte = G_tx_buf[G_tx_tail];
mgottscho 1:2a3bbec22035 154 G_tx_tail = (G_tx_tail + 1) % BUFFER_SIZE;
mgottscho 1:2a3bbec22035 155
mgottscho 1:2a3bbec22035 156 // Send first character to start tx interrupts, if stopped
mgottscho 1:2a3bbec22035 157 G_console.putc(temp_byte);
mgottscho 1:2a3bbec22035 158 }
mgottscho 1:2a3bbec22035 159
mgottscho 1:2a3bbec22035 160 // End critical section
mgottscho 1:2a3bbec22035 161 __enable_irq();
mgottscho 1:2a3bbec22035 162
mgottscho 1:2a3bbec22035 163 G_red_led = 1;
mgottscho 1:2a3bbec22035 164
mgottscho 1:2a3bbec22035 165 return i;
mgottscho 1:2a3bbec22035 166 }*/
mgottscho 1:2a3bbec22035 167
mgottscho 1:2a3bbec22035 168
mgottscho 1:2a3bbec22035 169 uint32_t Utility::receiveLine(char *line, const uint32_t len) {
mgottscho 1:2a3bbec22035 170 int i = 0;
mgottscho 1:2a3bbec22035 171 char lastChar = '\0';
mgottscho 1:2a3bbec22035 172
mgottscho 1:2a3bbec22035 173 if (line == NULL) //check input
mgottscho 1:2a3bbec22035 174 return 0;
mgottscho 1:2a3bbec22035 175
mgottscho 1:2a3bbec22035 176 // Start critical section - don't interrupt while changing global buffer variables
mgottscho 4:28f50e540872 177 __disable_uart_irq();
mgottscho 1:2a3bbec22035 178
mgottscho 1:2a3bbec22035 179 while (i < len && lastChar != '\r') { //Loop until maximum number of characters or a newline symbol
mgottscho 1:2a3bbec22035 180 //Wait for more characters if the rx buffer is empty
mgottscho 1:2a3bbec22035 181 if (__rx_tail == __rx_head) {
mgottscho 1:2a3bbec22035 182 // End critical section - need to allow rx interrupt to get new characters for buffer
mgottscho 4:28f50e540872 183 __enable_uart_irq();
mgottscho 1:2a3bbec22035 184 while (__rx_tail == __rx_head) { } //Spinloop until there are some characters
mgottscho 1:2a3bbec22035 185 // Start critical section - don't interrupt while changing global buffer variables
mgottscho 4:28f50e540872 186 __disable_uart_irq();
mgottscho 1:2a3bbec22035 187 }
mgottscho 1:2a3bbec22035 188
mgottscho 1:2a3bbec22035 189 lastChar = __rx_buf[__rx_tail];
mgottscho 1:2a3bbec22035 190 if (lastChar == '\r') //newline symbol
mgottscho 1:2a3bbec22035 191 line[i] = '\0';
mgottscho 1:2a3bbec22035 192 else
mgottscho 1:2a3bbec22035 193 line[i] = lastChar;
mgottscho 1:2a3bbec22035 194 i++;
mgottscho 1:2a3bbec22035 195 __rx_tail = (__rx_tail + 1) % BUFFER_SIZE;
mgottscho 1:2a3bbec22035 196 }
mgottscho 1:2a3bbec22035 197
mgottscho 1:2a3bbec22035 198 //Clear flag
mgottscho 1:2a3bbec22035 199 __have_rx_serial = false;
mgottscho 1:2a3bbec22035 200
mgottscho 1:2a3bbec22035 201 // End critical section
mgottscho 4:28f50e540872 202 __enable_uart_irq();
mgottscho 1:2a3bbec22035 203
mgottscho 1:2a3bbec22035 204 return i;
mgottscho 1:2a3bbec22035 205 }
mgottscho 1:2a3bbec22035 206
mgottscho 1:2a3bbec22035 207 bool Utility::haveRxSerialData() {
mgottscho 1:2a3bbec22035 208 return __have_rx_serial;
mgottscho 1:2a3bbec22035 209 }
mgottscho 1:2a3bbec22035 210
mgottscho 0:cc61e9d1c295 211 void Utility::__greenLED_ISR() {
mgottscho 3:87ce0325374d 212 if (green_led == 0) //Just flip the LED status every time we are called
mgottscho 3:87ce0325374d 213 green_led = 1;
mgottscho 0:cc61e9d1c295 214 else
mgottscho 3:87ce0325374d 215 green_led = 0;
mgottscho 0:cc61e9d1c295 216 }
mgottscho 0:cc61e9d1c295 217
mgottscho 0:cc61e9d1c295 218 void Utility::__redLED_ISR() {
mgottscho 3:87ce0325374d 219 if (red_led == 0) //Just flip the LED status every time we are called
mgottscho 3:87ce0325374d 220 red_led = 1;
mgottscho 0:cc61e9d1c295 221 else
mgottscho 3:87ce0325374d 222 red_led = 0;
mgottscho 1:2a3bbec22035 223 }
mgottscho 1:2a3bbec22035 224
mgottscho 1:2a3bbec22035 225 void Utility::__console_rx_ISR() {
mgottscho 1:2a3bbec22035 226 char tmp;
mgottscho 1:2a3bbec22035 227
mgottscho 1:2a3bbec22035 228 //Loop while the UART inbound FIFO is not empty and the receiving buffer is not full
mgottscho 1:2a3bbec22035 229 while (console.readable() && (__rx_head != (__rx_tail - 1) % BUFFER_SIZE)) {
mgottscho 1:2a3bbec22035 230 tmp = console.getc(); //read a byte into the buffer from the serial port
mgottscho 1:2a3bbec22035 231 __rx_buf[__rx_head] = tmp;
mgottscho 1:2a3bbec22035 232 __rx_head = (__rx_head + 1) % BUFFER_SIZE;
mgottscho 1:2a3bbec22035 233 if (tmp == '\r')
mgottscho 1:2a3bbec22035 234 __have_rx_serial = true;
mgottscho 1:2a3bbec22035 235 }
mgottscho 3:87ce0325374d 236
mgottscho 3:87ce0325374d 237 if (__user_fptr != NULL) //user callback
mgottscho 3:87ce0325374d 238 __user_fptr->call();
mgottscho 1:2a3bbec22035 239 }
mgottscho 1:2a3bbec22035 240
mgottscho 1:2a3bbec22035 241 //THIS DOES NOT WORK YET
mgottscho 1:2a3bbec22035 242 /*void Utility::__console_tx_ISR() {
mgottscho 1:2a3bbec22035 243 //Loop while the UART outbound FIFO is not full and the transmitting buffer is not empty
mgottscho 1:2a3bbec22035 244 while (G_console.writeable() && (G_tx_tail != G_tx_head)) {
mgottscho 1:2a3bbec22035 245 G_console.putc(G_tx_buf[G_tx_tail]); //write a byte to the serial port from the buffer
mgottscho 1:2a3bbec22035 246 G_tx_tail = (G_tx_tail + 1) % BUFFER_SIZE;
mgottscho 1:2a3bbec22035 247 }
mgottscho 4:28f50e540872 248 }*/
mgottscho 4:28f50e540872 249
mgottscho 4:28f50e540872 250 inline void Utility::__disable_uart_irq() {
mgottscho 4:28f50e540872 251 // Start critical section - don't interrupt with serial I/O
mgottscho 4:28f50e540872 252 // Since user specifies UART TX/RX pins, we don't know which we are using, so disable all 3
mgottscho 4:28f50e540872 253 NVIC_DisableIRQ(UART0_IRQn);
mgottscho 4:28f50e540872 254 NVIC_DisableIRQ(UART1_IRQn);
mgottscho 4:28f50e540872 255 NVIC_DisableIRQ(UART2_IRQn);
mgottscho 4:28f50e540872 256 }
mgottscho 4:28f50e540872 257
mgottscho 4:28f50e540872 258 inline void Utility::__enable_uart_irq() {
mgottscho 4:28f50e540872 259 // End critical section - can now interrupt with serial I/O
mgottscho 4:28f50e540872 260 // Since user specifies UART TX/RX pins, we don't know which we are using, so enable all 3
mgottscho 4:28f50e540872 261 NVIC_EnableIRQ(UART0_IRQn);
mgottscho 4:28f50e540872 262 NVIC_EnableIRQ(UART1_IRQn);
mgottscho 4:28f50e540872 263 NVIC_EnableIRQ(UART2_IRQn);
mgottscho 4:28f50e540872 264 }