System Management code
Dependencies: mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP
Fork of SystemManagement by
Revision 33:6bc82b6b62e5, committed 2015-01-06
- Comitter:
- pspatel321
- Date:
- Tue Jan 06 20:45:26 2015 +0000
- Parent:
- 32:e70407021ad2
- Child:
- 34:18bcf276d3bf
- Commit message:
- Updated IDs to match AMS, added a constants.h file.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Constants.h Tue Jan 06 20:45:26 2015 +0000 @@ -0,0 +1,19 @@ +#ifndef CONSTANTS_H +#define CONSTATNS_H + +#define BAUD 460800 // Serial port baud rate +#define CHAR_TIME 0.00002 // Time to send 1 char @ above baud +#define TX_SIZE 1000 // Serial buffer TX size +#define RX_SIZE 100 // Serial buffer RX size + +#define XBEE_BAUD 250000 // 250k baud serial for xbees +#define XBEE_TX_SIZE 1000 // Serial buffer TX size for xbees +#define XBEE_RX_SIZE 100 // Serial buffer RX size for xbees + +#define START_DELAY 10 // Startup delay for latch monitor circuits +#define FAST_LOOP 0.01 // Period (seconds) for fast loop (sampling, filters) +#define GATHER_LOOP 0.1 // Period (seconds) for main data processing loop +#define WDT_TIME 0.1 // Normal, running mode WDT timeout +#define CAN_LOOP 0.1 // Output period for CAN transmissions + +#endif \ No newline at end of file
--- a/IOobjects/CAN_Filter_LUT.h Sun Nov 16 02:43:58 2014 +0000 +++ b/IOobjects/CAN_Filter_LUT.h Tue Jan 06 20:45:26 2015 +0000 @@ -39,7 +39,7 @@ // STANDARD ID RANGES - CAN CONTROLLER 2 //( 0xLOWERBOUND & STDMASK | 1<<13) << 16 | ( 0xUPPERBOUND & STDMASK | 1<<13), lower/upperbounds are inclusive -//( 0xLOWERBOUND & STDMASK | 1<<13) << 16 | ( 0xUPPERBOUND & STDMASK | 1<<13), lower/upperbounds are inclusive +( 0x200 & STDMASK | 1<<13) << 16 | ( 0x7FF & STDMASK | 1<<13), //lower/upperbounds are inclusive, 0x200 to 0x7FF includes everything except motor controller messages };
--- a/IOobjects/CAN_RxIDs.h Sun Nov 16 02:43:58 2014 +0000 +++ b/IOobjects/CAN_RxIDs.h Tue Jan 06 20:45:26 2015 +0000 @@ -1,15 +1,18 @@ #ifndef CAN_RXIDS_H #define CAN_RXIDS_H +#define BASE_ID 0x500 // Start at 0x500 for this device + // Receive IDs -#define FAN_CONTROL_ID 0x480 -#define PUMP_CONTROL_ID 0x481 -#define DCDC_CONTROL_ID 0x482 +#define FAN_CONTROL_ID BASE_ID + 80 +#define PUMP_CONTROL_ID BASE_ID + 81 +#define DCDC_CONTROL_ID BASE_ID + 82 -#define AMS_RELAYS_ID 0x30E +#define GLVBAT_CLEARSOC_ID BASE_ID + 90 +#define GLVBAT_CLEARAH_ID BASE_ID + 91 +#define GLVBAT_SETCAPAC_ID BASE_ID + 92 -#define GLVBAT_CLEARSOC_ID 0x490 -#define GLVBAT_CLEARAH_ID 0x491 -#define GLVBAT_SETCAPAC_ID 0x492 +#define AMS_RELAYS_ID 0x303 +#define STEERING_RESET_ID 0x602 #endif \ No newline at end of file
--- a/IOobjects/CAN_TxIDs.h Sun Nov 16 02:43:58 2014 +0000 +++ b/IOobjects/CAN_TxIDs.h Tue Jan 06 20:45:26 2015 +0000 @@ -1,36 +1,38 @@ #ifndef CAN_TXIDS_H #define CAN_TXIDS_H +#define BASE_ID 0x500 // Start at 0x500 for this device + // Transmit IDs - System Mgmt Specific // Operating diagnostics -#define SYS_ERROR_ID 0x400 // Error frame - critical errors that require shutdown -#define SYS_XBEE1_ID 0x401 // Message in/out counter for xbee1 -#define SYS_XBEE2_ID 0x402 // Message in/out counter for xbee2 -#define SYS_TEMP_ID 0x403 // Internal temperature of the glv battery chargerFET +#define SYS_ERROR_ID BASE_ID + 00 // Error frame - critical errors that require shutdown +#define SYS_XBEE1_ID BASE_ID + 01 // Message in/out counter for xbee1 +#define SYS_XBEE2_ID BASE_ID + 02 // Message in/out counter for xbee2 +#define SYS_TEMP_ID BASE_ID + 03 // Internal temperature of the glv battery chargerFET // GLV Battery -#define SYS_GLV_CURRENT_ID 0x410 // GLV battery current -#define SYS_GLV_CAPACITY_ID 0x411 // GLV battery capacity setting -#define SYS_GLV_AH_ID 0x412 // GLV battery amphours -#define SYS_GLV_SOC_ID 0x413 // GLV battery SOC +#define SYS_GLV_CURRENT_ID BASE_ID + 10 // GLV battery current +#define SYS_GLV_CAPACITY_ID BASE_ID + 11 // GLV battery capacity setting +#define SYS_GLV_AH_ID BASE_ID + 12 // GLV battery amphours +#define SYS_GLV_SOC_ID BASE_ID + 13 // GLV battery SOC // DC-DC Converter -#define SYS_DCDC_CURRENT_ID 0x420 // DC-DC current -#define SYS_DCDC_STATUS_ID 0x421 // DC-DC status byte +#define SYS_DCDC_CURRENT_ID BASE_ID + 20 // DC-DC current +#define SYS_DCDC_STATUS_ID BASE_ID + 21 // DC-DC status byte // PWM Channels -#define SYS_PWM_FAN_ID 0x430 // FAN1 actual pwm -#define SYS_PWM_PUMP_ID 0x431 // PUMP1 actual pwm +#define SYS_PWM_FAN_ID BASE_ID + 30 // FAN1 actual pwm +#define SYS_PWM_PUMP_ID BASE_ID + 31 // PUMP1 actual pwm // IMD -#define SYS_IMD_STATUS_ID 0x440 // IMD status byte -#define SYS_IMD_RESIST_ID 0x441 // IMD resistance measurement +#define SYS_IMD_STATUS_ID BASE_ID + 40 // IMD status byte +#define SYS_IMD_RESIST_ID BASE_ID + 41 // IMD resistance measurement // Latch Supervisor states -#define SYS_IMD_LATCH_ID 0x450 // IMD Latch circuit error byte -#define SYS_AMS_LATCH_ID 0x451 // AMS Latch circuit error byte +#define SYS_IMD_LATCH_ID BASE_ID + 50 // IMD Latch circuit error byte +#define SYS_AMS_LATCH_ID BASE_ID + 51 // AMS Latch circuit error byte // Shutdown Switches -#define SYS_SWITCHES_ID 0x460 // Shutdown Switch State +#define SYS_SWITCHES_ID BASE_ID + 60 // Shutdown Switch State #endif \ No newline at end of file
--- a/IOobjects/IOobjects.cpp Sun Nov 16 02:43:58 2014 +0000 +++ b/IOobjects/IOobjects.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -1,5 +1,6 @@ #include "IOobjects.h" +Watchdog wdt(1); // Watchdog timer (TIMEOUT (sec)) LPCDigitalIn sw[]={ // Shutdown switch sense lines LPCDigitalIn(p1_0, PullUp), // Sense0 - fuse power LPCDigitalIn(p1_1, PullUp), // Sense1 - AMS latch @@ -14,20 +15,20 @@ LPCDigitalIn(p1_27, PullUp), // Sense10 - HVD/Charger LPCDigitalIn(p1_28, PullUp), // Sense11 - TSMS/tractive enable }; - CANBuffer can(CAN2, MEDIUM, p4_28); // Buffered CAN interface (PORT, SPEED, SILENT PIN) -CoulombCounter glvBat(p19, 10); // Coulomb counter battery monitor for GLV Battery (CURRENT SENSE PIN, INTEGRATION TIME) +CoulombCounter glvBat(p19, FAST_LOOP*1000); // Coulomb counter battery monitor for GLV Battery (CURRENT SENSE PIN, INTEGRATION TIME) DC_DC dcdc(p18, p20, p26, p25, p24, p23, 0.01, 1); // DC-DC converter & high-current load control (CONTROL PIN< CURRENT SENSE PIN, FAN1 PIN, FAN2 PIN, PUMP1 PIN, PUMP2 PIN, PWM PERIOD (sec), FULL-SCALE SLEW (sec)) IMD imd(p1_26); // IMD PWM sense channel to read status and resistance (IMD PWM PIN) -LatchMonitor AMSlatch(p0_18, p0_22, 15000); // Supervisor for AMS hardware latch/reset circuit (OK PIN, FAULT PIN, STARTUP DELAY (ms)) -LatchMonitor IMDlatch(p0_17, p0_21, 15000); // Supervisor for IMD hardware latch/reset circuit (OK PIN, FAULT PIN, STARTUP DELAY (ms)) -MODSERIAL pc(USBTX, USBRX, 3072, 256); // Serial to computer for diagnostics, 3kB output buffer, 256 byte input buffer +LatchMonitor AMSlatch(p0_18, p0_22, START_DELAY*1000); // Supervisor for AMS hardware latch/reset circuit (OK PIN, FAULT PIN, STARTUP DELAY (ms)) +LatchMonitor IMDlatch(p0_17, p0_21, START_DELAY*1000); // Supervisor for IMD hardware latch/reset circuit (OK PIN, FAULT PIN, STARTUP DELAY (ms)) +MODSERIAL pc(USBTX, USBRX, TX_SIZE, RX_SIZE); // Serial to computer for diagnostics, 3kB output buffer, 256 byte input buffer Temperature internalTmp(&NXFT15XH103_TABLE, p15); // Temperature conversion look-up table for internal temperature on the GLV bat charger FET (TABLE PTR, PIN) PollSwitch switches(sw, sizeof(sw)/sizeof(sw[0])); // Shutdown switch sense pins (SWITCH PIN ARRAY, NUM PINS) -Watchdog wdt(0.25); // Watchdog timer (TIMEOUT (sec)) -//Xbee xbee1(p9, p10, 250000, 1000, '\n'); // Software buffered Xbee 1 of 2 for wireless comms (TX, RX, BAUD, BUFFERSIZE, DELIM CHAR) -//Xbee xbee2(p13, p14, 250000, 1000, '\n'); // Software buffered Xbee 2 of 2 for wireless comms (TX, RX, BAUD, BUFFERSIZE, DELIM CHAR) -XbeeRelay xbee; + +CANxbee xbee1(p9, p10, XBEE_BAUD, XBEE_TX_SIZE, XBEE_RX_SIZE); +CANxbee xbee2(p13, p14, XBEE_BAUD, XBEE_TX_SIZE, XBEE_RX_SIZE); +XbeeManager xbeeRelay(&xbee1, &xbee2); +//XbeeRelay xbee; DigitalOut extras[] = {(p16), (p17)}; // Unused analog pins driven low Inputs data;
--- a/IOobjects/IOobjects.h Sun Nov 16 02:43:58 2014 +0000 +++ b/IOobjects/IOobjects.h Tue Jan 06 20:45:26 2015 +0000 @@ -2,7 +2,9 @@ #define _IO_OBJECTS_H #include "mbed.h" -#include "rtos.h" +#include "Constants.h" +#include "CAN_RxIDs.h" +#include "CAN_TxIDs.h" #include "CANBuffer.h" #include "CoulombCounter.h" #include "DC_DC.h" @@ -12,8 +14,11 @@ #include "PollSwitch.h" #include "Temperature.h" #include "Watchdog.h" -#include "Xbee.h" -#include "XbeeRelay.h" +#include "XbeeManager.h" +//#include "XbeeRelay.h" + +#define OS_TIMERPRIO 6 +#include "rtos.h" extern CANBuffer can; extern CoulombCounter glvBat; @@ -25,56 +30,52 @@ extern PollSwitch switches; extern Temperature internalTmp; extern Watchdog wdt; -extern XbeeRelay xbee; +//extern XbeeRelay xbee; +extern XbeeManager xbeeRelay; // Shared data updated by producer threads class Inputs { public: - volatile float glvCurrent; - volatile float glvAmphours; - volatile float glvSOC; - volatile float glvCapacity; - volatile bool glvOverCurrent; // Error bit, turn off car + float glvCurrent; + float glvAmphours; + float glvSOC; + float glvCapacity; + bool glvOverCurrent; // Error bit, turn off car - volatile char dcdcStatus; - volatile bool dcdcError; // Error bit, turn off car - volatile float dcdcCurrent; - volatile float dcdcFan1Duty; - volatile float dcdcFan2Duty; - volatile float dcdcPump1Duty; - volatile float dcdcPump2Duty; + char dcdcStatus; + bool dcdcError; // Error bit, turn off car + float dcdcCurrent; + float dcdcFan1Duty; + float dcdcFan2Duty; + float dcdcPump1Duty; + float dcdcPump2Duty; - volatile char imdStatus; - volatile float imdResistance; - volatile bool imdError; // Error bit, turn off car + char imdStatus; + float imdResistance; + bool imdError; // Error bit, turn off car - volatile char AMSlatchError; // Error bit, turn off car - volatile char IMDlatchError; // Error bit, turn off car + char AMSlatchError; // Error bit, turn off car + char IMDlatchError; // Error bit, turn off car - volatile char switchState; - - volatile float internalTemp; - volatile bool internalOverTemp; // Error bit, turn off car + char switchState; - volatile unsigned int xbee1MessagesIn; - volatile unsigned int xbee2MessagesIn; - volatile unsigned int xbee1MessagesOut; - volatile unsigned int xbee2MessagesOut; - - volatile bool watchdogReset; // Error bit, turn off car - volatile bool canFault; // Error bit, turn off car + float internalTemp; + bool internalOverTemp; // Error bit, turn off car + + bool watchdogReset; // Error bit, turn off car + bool canFault; // Error bit, turn off car - volatile char errorFrame; + char errorFrame; }; // Shared data updated by CAN messeges class CANinputs { public: - volatile bool airsClosed; - volatile float dcdcFan1Duty; - volatile float dcdcFan2Duty; - volatile float dcdcPump1Duty; - volatile float dcdcPump2Duty; + bool airsClosed; + float dcdcFan1Duty; + float dcdcFan2Duty; + float dcdcPump1Duty; + float dcdcPump2Duty; }; extern CANinputs CANdata;
--- a/Libs/CoulombCounter/CoulombCounter.cpp Sun Nov 16 02:43:58 2014 +0000 +++ b/Libs/CoulombCounter/CoulombCounter.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -16,12 +16,11 @@ if (capReg < 1.0 || capReg > 5.0) { // Bad, write default store.write(defaultAh, rtcGPREG_capacity); } - capReg = store.read(rtcGPREG_capacity); // Default SOC if blank or corrupted float Ah = store.read(rtcGPREG_counter); - if (Ah < 0 || Ah > capReg) { // Bad, write default - store.write(defaultSOC*capReg, rtcGPREG_counter); + if (Ah < 0 || Ah > defaultAh) { // Bad, write default + store.write(defaultSOC*defaultAh, rtcGPREG_counter); } // Take the initial readings, fill the buffer
--- a/Libs/MODDMA.lib Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/AjK/code/MODDMA/#97a16bf2ff43
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Libs/MODSERIAL.lib Tue Jan 06 20:45:26 2015 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/AjK/code/MODSERIAL/#ae0408ebdd68
--- a/Libs/MODSERIAL/ChangeLog.c Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/* $Id:$ - -1.25 8th January 2013 - - * Bring back into line with MBed libraries. - * Credits: - Erik Olieman : http://mbed.org/users/Sissors/code/MODSERIAL/rev/3ba4341d74d6 - Erik Olieman : http://mbed.org/users/Sissors/code/MODSERIAL/rev/a469aa702bab - - -1.24 6th Dec 2012 - - * Beta release for new Mbed library. - -1.23 25th July 2012 - - * LPC1768 code as was. This release includes "alpha" support for the LPC11U24 - -1.22 19th April 2012 - - * http://mbed.org/forum/bugs-suggestions/topic/2936/ - * Bug fix, protect important buffer pointers from IRQ corruption. - * Credits: - Anthony Wieser http://mbed.org/users/WieserSoftwareLtd/ for the fix. - BlazeX http://mbed.org/users/BlazeX/ for the alert that a fix was needed! - -1.21 10 May 2011 - - * http://mbed.org/forum/mbed/topic/2264 - -1.20 26 April 2011 - - * Bug fix, not blocking on transmit - by Erik Petrich, http://mbed.org/forum/bugs-suggestions/topic/2200 - -1.19 20 April 2011 - - * Fixed some doxygen comment bugs. - -1.18 20 April 2011 - - * All callbacks now use MODSERIAL_callback (rather than Mbed's FunctionPointer[1] type) - to store and invoke it's callbacks. This allows MODSERIAL to pass a parameter - to callbacks. The function prototype is now void func(MODSERIAL_IRQ_INFO *q). - * Callbacks now pass a pointer to a MODSERIAL_IRQ_INFO class type. - This class holds a pointer to the MODSERIAL object that invoked the callback - thus freeing callbacks need to use the global variable of the original - MODSERIAL instance. - * MODSERIAL_IRQ_INFO also declares public functions that are protected within MODSERIAL - thus allowing certain functions to be restricted to callback context only. - * New function MODSERIAL_IRQ_INFO::rxDiscardLastChar() allows an rxCallback function - to remove the character that was just placed into the RX buffer. - - [1] http://mbed.org/users/AjK/libraries/FPointer/latest/docs/ - -1.17 08/Mar/2011 - Fixed a memory leak in the DMA code. - -1.16 - 12 Feb 2011 - - * Missed one, doh! - -1.15 - 12 Feb 2011 - - * Fixed some typos. - -1.14 - 7 Feb 2011 - - * Fixed a bug in __putc() that caused the output buffer pointer to - become corrupted. - -1.13 - 20/01/2011 - - * Added extra documentation. - * Fixed some typos. - -1.12 - 20/01/2011 - - * Added new "autoDetectChar()" function. To use:- - 1st: Add a callback to invoke when the char is detected:- - .attach(&detectedChar, MODSERIAL::RxAutoDetect); - 2nd: Send the char to detect. - .autoDectectChar('\n'); - Whenever that char goes into the RX buffer your callback will be invoked. - Added example2.cpp to demo a simple messaging system using this auto feature. - - -1.11 - 23/11/2010 - - * Fixed a minor issue with 1.10 missed an alteration of name change. - -1.10 - 23/11/2010 - - * Rename the DMA callback from attach_dma_complete() to attach_dmaSendComplete() - -1.9 - 23/11/2010 - - * Added support for DMA sending of characters. Required is - the MODDMA library module:- - http://mbed.org/users/AjK/libraries/MODDMA/latest - See example_dma.cpp for more information. - -1.8 - 22/11/2010 - - * Added code so that if a buffer is set to zero length then - MODSERIAL defaults to just using the FIFO for that stream - thus making the library "fall back" to teh same operation - that the Mbed Serial library performs. - * Removed dmaSend() function that should have been removed - at 1.7 - -1.7 - 21/11/2010 - - * Remove the DMA enum from MODSERIAL.h as it's not currently - ready for release. - * Added page doxygen comments. - -1.6 - 21/11/2010 - - * Version 1.5 solved a blocking problem on putc() when called - from another ISR. However, isr_tx() invokes a callback of it's - own when a byte is tranferred from TX buffer to TX FIFO. User - programs may interpret that as an IRQ callback. That's an ISR - call from within an existing ISR which is not good. So the - TxIrq callback from isr_tx is now conditional. It will only - be called when isr_tx() is actually within it's own ISR and - not when called from alternate ISR handlers. - -1.5 - 21/11/2010 - - * Calling putc() (or any derived function that uses it like - printf()) while inside an interrupt service routine can - cause the system to lock up if the TX buffer is full. This - is because bytes are only transferred from the TX buffer to - the TX FIFO via the TX ISR. If we are, say in an RX ISR already, - then the TX ISR will never trigger. The TX buffer stays full and - there is never space to putc() the byte. So, while putc() blocks - waiting for space it calls isr_tx() to ensure if TX FIFO space - becomes available it will move bytes from the TX buffer to TX - FIFO thus removing the blocking condition within putc(). - -1.4 - 21/11/2010 - - * Removed all the new DMA code. I wish mbed.org had proper SVN - versioning, I'm use to working in HEAD and BRANCHES after I've - released a project. Getting bug reports in current releases - while trying to dev new code is hard to manage without source - control of some type! - -1.3 - 21/11/2010 - - * Fixed a macro problem with txIsBusy() - * Started adding code to use "block data" sending using DMA - * Removed #include "IOMACROS.h" - -1.2 - 21/11/2010 - - * Removed unsed variables from flushBuffer() - * Fixed a bug where both RX AND TX fifos are cleared/reset - when just TX OR RX should be cleared. - * Fixed a bug that cleared IIR when in fact it should be left - alone so that any pending interrupt after flush is handled. - * Merged setBase() into init() as it wasn't required anywhere else. - * Changed init() to enforce _uidx is set by Serial to define the _base - address of the Uart in use. - -1.1 - 20/11/2010 - - * Added this file - * Removed cruft from GETC.cpp - * "teh" should be "the", why do my fingers do that? - -1.0 - 20/11/2010 - - * First release. - -*/ \ No newline at end of file
--- a/Libs/MODSERIAL/FLUSH.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODSERIAL.h" -#include "MACROS.h" - -namespace AjK { - -void -MODSERIAL::flushBuffer(IrqType type) -{ - uint32_t ier = _IER; - switch(type) { - case TxIrq: _IER &= ~(1UL << 1); break; - case RxIrq: _IER &= ~(1UL << 0); break; - } - buffer_in[type] = 0; - buffer_out[type] = 0; - buffer_count[type] = 0; - buffer_overflow[type] = 0; - switch(type) { - case TxIrq: _FCR = MODSERIAL_FIFO_TX_RESET; break; - case RxIrq: _FCR = MODSERIAL_FIFO_RX_RESET; break; - } - _IER = ier; -} - -}; // namespace AjK ends
--- a/Libs/MODSERIAL/GETC.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODSERIAL.h" -#include "MACROS.h" - -namespace AjK { - -int -MODSERIAL::__getc(bool block) -{ - // If no buffer is in use fall back to standard RX FIFO usage. - // Note, we must block in this case and ignore bool "block" - // so as to maintain compat with Mbed Serial. - if (buffer_size[RxIrq] == 0 || buffer[RxIrq] == (char *)NULL) { - while(! MODSERIAL_RBR_HAS_DATA ) ; - return (int)(_RBR & 0xFF); - } - - if (block) { while ( MODSERIAL_RX_BUFFER_EMPTY ) ; } // Blocks. - else if ( MODSERIAL_RX_BUFFER_EMPTY ) return -1; - - int c = buffer[RxIrq][buffer_out[RxIrq]]; - buffer_out[RxIrq]++; - if (buffer_out[RxIrq] >= buffer_size[RxIrq]) { - buffer_out[RxIrq] = 0; - } - - // If we have made space in the RX Buffer then copy over - // any characters in the RX FIFO that my reside there. - // Temporarily disable the RX IRQ so that we do not re-enter - // it under interrupts. - if ( ! MODSERIAL_RX_BUFFER_FULL ) { - uint32_t ier = _IER; - _IER &= ~(1UL << 0); - isr_rx(); - _IER = ier; - } - - __disable_irq(); - buffer_count[RxIrq]--; - __enable_irq(); - return c; -} - -}; // namespace AjK ends
--- a/Libs/MODSERIAL/INIT.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODSERIAL.h" -#include "MACROS.h" - - -namespace AjK { - -void -MODSERIAL::init( int txSize, int rxSize, PinName rx ) -{ - disableIrq(); - - callbackInfo.setSerial(this); - -#ifdef __LPC11UXX_H__ - - _base = LPC_USART; - -#else - switch( _serial.index ) { - case 0: _base = LPC_UART0; break; - case 1: _base = LPC_UART1; break; - case 2: _base = LPC_UART2; break; - case 3: _base = LPC_UART3; break; - default: _base = NULL; break; - } -#endif - - dmaSendChannel = -1; - moddma_p = (void *)NULL; - - if ( _base != NULL ) { - buffer_size[RxIrq] = rxSize; - buffer[RxIrq] = rxSize > 0 ? (char *)malloc(buffer_size[RxIrq]) : (char *)NULL; - buffer_in[RxIrq] = 0; - buffer_out[RxIrq] = 0; - buffer_count[RxIrq] = 0; - buffer_overflow[RxIrq] = 0; - Serial::attach( this, &MODSERIAL::isr_rx, Serial::RxIrq ); - - buffer_size[TxIrq] = txSize; - buffer[TxIrq] = txSize > 0 ? (char *)malloc(buffer_size[TxIrq]) : (char *)NULL; - buffer_in[TxIrq] = 0; - buffer_out[TxIrq] = 0; - buffer_count[TxIrq] = 0; - buffer_overflow[TxIrq] = 0; - Serial::attach( this, &MODSERIAL::isr_tx, Serial::TxIrq ); - } - else { - error("MODSERIAL must have a defined UART to function."); - } - - _FCR = MODSERIAL_FIFO_ENABLE | MODSERIAL_FIFO_RX_RESET | MODSERIAL_FIFO_TX_RESET; - - auto_detect_char = 0; - - enableIrq(); -} - -}; // namespace AjK ends
--- a/Libs/MODSERIAL/ISR_RX.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODSERIAL.h" -#include "MACROS.h" - -namespace AjK { - -void -MODSERIAL::isr_rx(void) -{ - if (! _base || buffer_size[RxIrq] == 0 || buffer[RxIrq] == (char *)NULL) { - _isr[RxIrq].call(&this->callbackInfo); - return; - } - - while( MODSERIAL_RBR_HAS_DATA ) { - rxc = (char)(_RBR & 0xFF); - if ( MODSERIAL_RX_BUFFER_FULL ) { - buffer_overflow[RxIrq] = rxc; // Oh dear, no room in buffer. - _isr[RxOvIrq].call(&this->callbackInfo); - } - else { - if (buffer[RxIrq] != (char *)NULL) { - buffer[RxIrq][buffer_in[RxIrq]] = rxc; - buffer_count[RxIrq]++; - buffer_in[RxIrq]++; - if (buffer_in[RxIrq] >= buffer_size[RxIrq]) { - buffer_in[RxIrq] = 0; - } - } - _isr[RxIrq].call(&this->callbackInfo); - } - if (auto_detect_char == rxc) { - _isr[RxAutoDetect].call(&this->callbackInfo); - } - } -} - -}; // namespace AjK ends -
--- a/Libs/MODSERIAL/ISR_TX.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODSERIAL.h" -#include "MACROS.h" - -namespace AjK { - -void -MODSERIAL::isr_tx(bool doCallback) -{ - if (! _base || buffer_size[TxIrq] == 0 || buffer[TxIrq] == (char *)NULL) { - _isr[TxIrq].call(&this->callbackInfo); - return; - } - - while (! MODSERIAL_TX_BUFFER_EMPTY && MODSERIAL_THR_HAS_SPACE ) { - _THR = txc = (uint8_t)(buffer[TxIrq][buffer_out[TxIrq]]); - buffer_count[TxIrq]--; - buffer_out[TxIrq]++; - if (buffer_out[TxIrq] >= buffer_size[TxIrq]) { - buffer_out[TxIrq] = 0; - } - if (doCallback) _isr[TxIrq].call(&this->callbackInfo); - } - - if ( MODSERIAL_TX_BUFFER_EMPTY ) { - _IER = 1; - _isr[TxEmpty].call(&this->callbackInfo); - } -} - -}; // namespace AjK ends - -
--- a/Libs/MODSERIAL/MACROS.h Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef MODSERIAL_MACROS_H -#define MODSERIAL_MACROS_H - -#define MODSERIAL_RBR 0x00 -#define MODSERIAL_THR 0x00 -#define MODSERIAL_DLL 0x00 -#define MODSERIAL_IER 0x04 -#define MODSERIAL_DML 0x04 -#define MODSERIAL_IIR 0x08 -#define MODSERIAL_FCR 0x08 -#define MODSERIAL_LCR 0x0C -#define MODSERIAL_LSR 0x14 -#define MODSERIAL_SCR 0x1C -#define MODSERIAL_ACR 0x20 -#define MODSERIAL_ICR 0x24 -#define MODSERIAL_FDR 0x28 -#define MODSERIAL_TER 0x30 - -#define MODSERIAL_LSR_RDR (1UL << 0) -#define MODSERIAL_LSR_OE (1UL << 1) -#define MODSERIAL_LSR_PE (1UL << 2) -#define MODSERIAL_LSR_FE (1UL << 3) -#define MODSERIAL_LSR_BR (1UL << 4) -#define MODSERIAL_LSR_THRE (1UL << 5) -#define MODSERIAL_LSR_TEMT (1UL << 6) -#define MODSERIAL_LSR_RXFE (1UL << 7) - -#define MODSERIAL_FIFO_ENABLE 1 -#define MODSERIAL_FIFO_RX_RESET 2 -#define MODSERIAL_FIFO_TX_RESET 4 - -#define _RBR *((char *)_base+MODSERIAL_RBR) -#define _THR *((char *)_base+MODSERIAL_THR) -#define _IIR *((char *)_base+MODSERIAL_IIR) -#define _IER *((char *)_base+MODSERIAL_IER) -#define _LSR *((char *)_base+MODSERIAL_LSR) -#define _FCR *((char *)_base+MODSERIAL_FCR) - -#define MODSERIAL_TX_BUFFER_EMPTY (buffer_count[TxIrq]==0) -#define MODSERIAL_RX_BUFFER_EMPTY (buffer_count[RxIrq]==0) -#define MODSERIAL_TX_BUFFER_FULL (buffer_count[TxIrq]==buffer_size[TxIrq]) -#define MODSERIAL_RX_BUFFER_FULL (buffer_count[RxIrq]==buffer_size[RxIrq]) - -#define MODSERIAL_THR_HAS_SPACE ((int)_LSR&MODSERIAL_LSR_THRE) -#define MODSERIAL_TEMT_IS_EMPTY ((int)_LSR&MODSERIAL_LSR_TEMT) -#define MODSERIAL_RBR_HAS_DATA ((int)_LSR&MODSERIAL_LSR_RDR) - -#endif
--- a/Libs/MODSERIAL/MODSERIAL.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - @file MODSERIAL.h - @purpose Extends Serial to provide fully buffered IO - @version 1.6 - @date Nov 2010 - @author Andy Kirkham -*/ - -#include "MODSERIAL.h" -#include "MACROS.h" - -namespace AjK { - -MODSERIAL::MODSERIAL( PinName tx, PinName rx, const char* name ) : Serial( tx, rx, name ) -{ - init( MODSERIAL_DEFAULT_TX_BUFFER_SIZE, MODSERIAL_DEFAULT_RX_BUFFER_SIZE, rx ); -} - -MODSERIAL::MODSERIAL( PinName tx, PinName rx, int bufferSize, const char* name ) : Serial( tx, rx, name ) -{ - init( bufferSize, bufferSize, rx ); -} - -MODSERIAL::MODSERIAL( PinName tx, PinName rx, int txSize, int rxSize, const char* name ) : Serial( tx, rx, name ) -{ - init( txSize, rxSize, rx ); -} - -MODSERIAL::~MODSERIAL() -{ - disableIrq(); - if ( buffer[0] != NULL) free((char *)buffer[0] ); - if ( buffer[1] != NULL) free((char *)buffer[1] ); -} - -bool -MODSERIAL::txBufferFull( void ) -{ - return MODSERIAL_TX_BUFFER_FULL; -} - -bool -MODSERIAL::rxBufferFull( void ) -{ - return MODSERIAL_RX_BUFFER_FULL; -} - -bool -MODSERIAL::txBufferEmpty( void ) -{ - return MODSERIAL_TX_BUFFER_EMPTY; -} - -bool -MODSERIAL::rxBufferEmpty( void ) -{ - return MODSERIAL_RX_BUFFER_EMPTY; -} - -bool -MODSERIAL::txIsBusy( void ) -{ - return ( _LSR & ( 3UL << 5 ) == 0 ) ? true : false; -} - -void -MODSERIAL::disableIrq( void ) -{ - -#ifdef __LPC11UXX_H__ - NVIC_DisableIRQ( UART_IRQn ); -#else - switch( _serial.index ) { - case 0: NVIC_DisableIRQ( UART0_IRQn ); break; - case 1: NVIC_DisableIRQ( UART1_IRQn ); break; - case 2: NVIC_DisableIRQ( UART2_IRQn ); break; - case 3: NVIC_DisableIRQ( UART3_IRQn ); break; - } -#endif -} - -void -MODSERIAL::enableIrq(void) -{ -#ifdef __LPC11UXX_H__ - NVIC_EnableIRQ( UART_IRQn ); -#else - switch( _serial.index ) { - case 0: NVIC_EnableIRQ( UART0_IRQn ); break; - case 1: NVIC_EnableIRQ( UART1_IRQn ); break; - case 2: NVIC_EnableIRQ( UART2_IRQn ); break; - case 3: NVIC_EnableIRQ( UART3_IRQn ); break; - } -#endif -} - -int -MODSERIAL::rxDiscardLastChar( void ) -{ - // This function can only be called indirectly from - // an rxCallback function. Therefore, we know we - // just placed a char into the buffer. - char c = buffer[RxIrq][buffer_in[RxIrq]]; - - if (buffer_count[RxIrq]) { - buffer_count[RxIrq]--; - buffer_in[RxIrq]--; - if (buffer_in[RxIrq] < 0) { - buffer_in[RxIrq] = buffer_size[RxIrq] - 1; - } - } - - return (int)c; -} - - -}; // namespace AjK ends
--- a/Libs/MODSERIAL/MODSERIAL.h Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1089 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - @file MODSERIAL.h - @purpose Extends Serial to provide fully buffered IO - @version see ChangeLog.c - @date Nov 2010 - @author Andy Kirkham -*/ - -#ifndef MODSERIAL_H -#define MODSERIAL_H - -/** @defgroup API The MODSERIAL API */ -/** @defgroup MISC Misc MODSERIAL functions */ -/** @defgroup INTERNALS MODSERIAL Internals */ - -#ifndef MODSERIAL_DEFAULT_RX_BUFFER_SIZE -#define MODSERIAL_DEFAULT_RX_BUFFER_SIZE 256 -#endif - -#ifndef MODSERIAL_DEFAULT_TX_BUFFER_SIZE -#define MODSERIAL_DEFAULT_TX_BUFFER_SIZE 256 -#endif - -#include "mbed.h" -#include "serial_api.h" - -namespace AjK { - -// Forward reference. -class MODSERIAL; - -/** - * @author Andy Kirkham - * @see http://mbed.org/cookbook/MODSERIAL - * @see example3a.cpp - * @see example3b.cpp - * @see API - * - * <b>MODSERIAL_IRQ_INFO</b> is a class used to pass information (and access to protected - * MODSERIAL functions) to IRQ callbacks. - */ -class MODSERIAL_IRQ_INFO -{ -public: - friend class MODSERIAL; - - MODSERIAL *serial; - - MODSERIAL_IRQ_INFO() { serial = 0; } - - /** rxDiscardLastChar() - * - * Remove the last char placed into the rx buffer. - * This is an operation that can only be performed - * by an rxCallback function. - * @ingroup API - * @return The byte removed from the buffer. - */ - int rxDiscardLastChar(void); - -protected: - - /** setSerial() - * - * Used internally by MODSERIAL to set the "this" pointer - * of the MODSERIAL that created this object. - * @ingroup INTERNAL - * @param A pointer to a MODSERIAL object instance. - */ - void setSerial(MODSERIAL *s) { serial = s; } -}; - -// Forward reference dummy class. -class MODSERIAL_callback_dummy; - -/** - * @author Andy Kirkham - * @see http://mbed.org/cookbook/MODSERIAL - * @see example3a.cpp - * @see example3b.cpp - * @see API - * - * <b>MODSERIAL_callback</b> is a class used to hold application callbacks that - * MODSERIAL can invoke on certain events. - */ -class MODSERIAL_callback -{ -protected: - - //! C callback function pointer. - void (*c_callback)(MODSERIAL_IRQ_INFO *); - - //! C++ callback object/method pointer (the object part). - MODSERIAL_callback_dummy *obj_callback; - - //! C++ callback object/method pointer (the method part). - void (MODSERIAL_callback_dummy::*method_callback)(MODSERIAL_IRQ_INFO *); - -public: - - /** Constructor - */ - MODSERIAL_callback() { - c_callback = 0; - obj_callback = 0; - method_callback = 0; - } - - /** attach - Overloaded attachment function. - * - * Attach a C type function pointer as the callback. - * - * Note, the callback function prototype must be:- - * @code - * void myCallbackFunction(MODSERIAL_IRQ_INFO *); - * @endcode - * @param A C function pointer to call. - */ - void attach(void (*function)(MODSERIAL_IRQ_INFO *) = 0) { c_callback = function; } - - /** attach - Overloaded attachment function. - * - * Attach a C++ type object/method pointer as the callback. - * - * Note, the callback method prototype must be:- - * @code - * public: - * void myCallbackFunction(MODSERIAL_IRQ_INFO *); - * @endcode - * @param A C++ object pointer. - * @param A C++ method within the object to call. - */ - template<class T> - void attach(T* item, void (T::*method)(MODSERIAL_IRQ_INFO *)) { - obj_callback = (MODSERIAL_callback_dummy *)item; - method_callback = (void (MODSERIAL_callback_dummy::*)(MODSERIAL_IRQ_INFO *))method; - } - - /** call - Overloaded callback initiator. - * - * call the callback function. - * - * @param A pointer to a MODSERIAL_IRQ_INFO object. - */ - void call(MODSERIAL_IRQ_INFO *arg) { - if (c_callback != 0) { - (*c_callback)(arg); - } - else { - if (obj_callback != 0 && method_callback != 0) { - (obj_callback->*method_callback)(arg); - } - } - } -}; - -/** - * @author Andy Kirkham - * @see http://mbed.org/cookbook/MODSERIAL - * @see http://mbed.org/handbook/Serial - * @see example1.cpp - * @see example2.cpp - * @see example3a.cpp - * @see example3b.cpp - * @see example_dma.cpp - * @see API - * - * <b>MODSERIAL</b> extends the Mbed library <a href="/handbook/Serial">Serial</a> to provide fully buffered - * TX and RX streams. Buffer length is fully customisable. - * - * Before using MODSERIAL users should be familar with Mbed's standard <a href="/handbook/Serial">Serial</a> - * library object. MODSERIAL is a direct "drop in" replacement for <a href="/handbook/Serial">Serial</a>. Where - * previously Serial was used, MODSERIAL can be used as adirect replacement instantly offering standard - * TX and RX buffering. By default, both TX and RX buffers are 256 bytes in length. - * - * @image html /media/uploads/mbedofficial/serial_interfaces.png - * - * Standard example: - * @code - * #include "mbed.h" - * #include "MODSERIAL.h" - * - * MODSERIAL pc(USBTX, USBRX); // tx, rx - * - * int main() { - * pc.printf("Hello World!"); - * while(1) { - * pc.putc(pc.getc() + 1); - * } - * } - * @endcode - * - * Example with alternate buffer length: - * @code - * #include "mbed.h" - * #include "MODSERIAL.h" - * - * // Make TX and RX buffers 512byes in length - * MODSERIAL pc(USBTX, USBRX, 512); // tx, rx - * - * int main() { - * pc.printf("Hello World!"); - * while(1) { - * pc.putc(pc.getc() + 1); - * } - * } - * @endcode - * - * Example with alternate buffer length: - * @code - * #include "mbed.h" - * #include "MODSERIAL.h" - * - * // Make TX 1024bytes and RX 512byes in length - * MODSERIAL pc(USBTX, USBRX, 1024, 512); // tx, rx - * - * int main() { - * pc.printf("Hello World!"); - * while(1) { - * pc.putc(pc.getc() + 1); - * } - * } - * @endcode - */ -class MODSERIAL : public Serial -{ -public: - - // Allow instances of MODSERIAL_IRQ_INFO to use protected properties and methods. - friend class MODSERIAL_IRQ_INFO; - - //! A copy of the Serial parity enum - /** @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.format */ - enum Parity { - None = 0 - , Odd - , Even - , Forced1 - , Forced0 - }; - - //! A copy of the Serial IrqType enum - enum IrqType { - RxIrq = 0 - , TxIrq - , RxOvIrq - , TxOvIrq - , TxEmpty - , RxAutoDetect - , NumOfIrqTypes - }; - - //! Non-blocking functions return code. - enum Result { - Ok = 0 /*!< Ok. */ - , NoMemory = -1 /*!< Memory allocation failed. */ - , NoChar = -1 /*!< No character in buffer. */ - , BufferOversize = -2 /*!< Oversized buffer. */ - }; - - /** - * The MODSERIAL constructor is used to initialise the serial object. - * - * @param tx PinName of the TX pin. - * @param rx PinName of the TX pin. - */ - MODSERIAL(PinName tx, PinName rx, const char* name = NULL); - - /** - * The MODSERIAL constructor is used to initialise the serial object. - * - * @param tx PinName of the TX pin. - * @param rx PinName of the TX pin. - * @param bufferSize Integer of the TX and RX buffer sizes. - */ - MODSERIAL(PinName tx, PinName rx, int bufferSize, const char* name = NULL); - - /** - * The MODSERIAL constructor is used to initialise the serial object. - * - * @param tx PinName of the TX pin. - * @param rx PinName of the TX pin. - * @param txBufferSize Integer of the TX buffer sizes. - * @param rxBufferSize Integer of the RX buffer sizes. - */ - MODSERIAL(PinName tx, PinName rx, int txBufferSize, int rxBufferSize, const char* name = NULL); - - virtual ~MODSERIAL(); - - /** - * Function: attach - * - * The Mbed standard <a href="/handbook/Serial">Serial</a> library object allows an interrupt callback - * to be made when a byte is received by the TX or RX UART hardware. MODSERIAL traps these interrupts - * to enable it's buffering system. However, after the byte has been received/sent under interrupt control, - * MODSERIAL can callback a user function as a notification of the interrupt. Note, user code should not - * directly interact with the Uart hardware, MODSERIAL does that, instead, MODSERIAL API functions should - * be used. - * - * <b>Note</b>, a character is written out then, if there is room in the TX FIFO and the TX buffer is empty, - * putc() will put the character directly into THR (the output holding register). If the TX FIFO is full and - * cannot accept the character, it is placed into the TX output buffer. The TX interrupts are then enabled - * so that when the TX FIFO empties, the TX buffer is then transferred to the THR FIFO. The TxIrq will ONLY - * be activated when this transfer of a character from BUFFER to THR FIFO takes place. If your character - * throughput is not high bandwidth, then the 16 byte TX FIFO may be enough and the TX output buffer may - * never come into play. - * - * @code - * #include "mbed.h" - * #include "MODSERIAL.h" - * - * DigitalOut led1(LED1); - * DigitalOut led2(LED2); - * DigitalOut led3(LED3); - * - * // To test, connect p9 to p10 as a loopback. - * MODSERIAL pc(p9, p10); - * - * // This function is called when a character goes into the TX buffer. - * void txCallback(void) { - * led2 = !led2; - * } - * - * // This function is called when a character goes into the RX buffer. - * void rxCallback(void) { - * led3 = !led3; - * } - * - * int main() { - * pc.baud(115200); - * pc.attach(&txCallback, MODSERIAL::TxIrq); - * pc.attach(&rxCallback, MODSERIAL::RxIrq); - * - * while(1) { - * led1 = !led1; - * wait(0.5); - * pc.putc('A'); - * wait(0.5); - * } - * ] - * @endcode - * - * @ingroup API - * @param fptr A pointer to a void function, or 0 to set as none - * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) - */ - void attach(void (*fptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { _isr[type].attach(fptr); } - - /** - * Function: attach - * - * The Mbed standard <a href="/handbook/Serial">Serial</a> library object allows an interrupt callback - * to be made when a byte is received by the TX or RX UART hardware. MODSERIAL traps these interrupts - * to enable it's buffering system. However, after the byte has been received/sent under interrupt control, - * MODSERIAL can callback a user function as a notification of the interrupt. Note, user code should not - * directly interact with the Uart hardware, MODSERIAL does that, instead, MODSERIAL API functions should - * be used. - * - * <b>Note</b>, a character is written out then, if there is room in the TX FIFO and the TX buffer is empty, - * putc() will put the character directly into THR (the output holding register). If the TX FIFO is full and - * cannot accept the character, it is placed into the TX output buffer. The TX interrupts are then enabled - * so that when the TX FIFO empties, the TX buffer is then transferred to the THR FIFO. The TxIrq will ONLY - * be activated when this transfer of a character from BUFFER to THR FIFO takes place. If your character - * throughput is not high bandwidth, then the 16 byte TX FIFO may be enough and the TX output buffer may - * never come into play. - * - * @code - * #include "mbed.h" - * #include "MODSERIAL.h" - * - * DigitalOut led1(LED1); - * DigitalOut led2(LED2); - * DigitalOut led3(LED3); - * - * // To test, connect p9 to p10 as a loopback. - * MODSERIAL pc(p9, p10); - * - * class Foo { - * public: - * // This method is called when a character goes into the TX buffer. - * void txCallback(void) { led2 = !led2; } - * - * // This method is called when a character goes into the RX buffer. - * void rxCallback(void) { led3 = !led3; } - * }; - * - * Foo foo; - * - * int main() { - * pc.baud(115200); - * pc.attach(&foo, &Foo::txCallback, MODSERIAL::TxIrq); - * pc.attach(&foo, &Foo::rxCallback, MODSERIAL::RxIrq); - * - * while(1) { - * led1 = !led1; - * wait(0.5); - * pc.putc('A'); - * wait(0.5); - * } - * ] - * @endcode - * - * @ingroup API - * @param tptr A pointer to the object to call the member function on - * @param mptr A pointer to the member function to be called - * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) - */ - template<typename T> - void attach(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { - if((mptr != 0) && (tptr != 0)) { - _isr[type].attach(tptr, mptr); - } - } - - /** - * @see attach - * @ingroup API - */ - void connect(void (*fptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { _isr[RxIrq].attach(fptr); } - - /** - * @see attach - * @ingroup API - */ - template<typename T> - void connect(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { - if((mptr != 0) && (tptr != 0)) { - _isr[type].attach(tptr, mptr); - } - } - - /** - * Function: writeable - * - * Determine if there is space available to write a byte - * - * @ingroup API - * @return 1 if there is space to write a character, else 0 - */ - int writeable() { return txBufferFull() ? 0 : 1; } - - /** - * Function: readable - * - * Determine if there is a byte available to read - * - * @ingroup API - * @return 1 if there is a character available to read, else 0 - */ - int readable() { return rxBufferEmpty() ? 0 : 1; } - - /** - * Function: txBufferSane - * - * Determine if the TX buffer has been initialized. - * - * @ingroup API - * @return true if the buffer is initialized, else false - */ - bool txBufferSane(void) { return buffer[TxIrq] != (char *)NULL ? true : false; } - - /** - * Function: rxBufferSane - * - * Determine if the RX buffer has been initialized. - * - * @ingroup API - * @return true if the buffer is initialized, else false - */ - bool rxBufferSane(void) { return buffer[TxIrq] != (char *)NULL ? true : false; } - - /** - * Function: txBufferGetCount - * - * Returns how many bytes are in the TX buffer - * - * @ingroup API - * @return The number of bytes in the TX buffer - */ - int txBufferGetCount(void) { return buffer_count[TxIrq]; } - - /** - * Function: rxBufferGetCount - * - * Returns how many bytes are in the RX buffer - * - * @ingroup API - * @return The number of bytes in the RX buffer - */ - int rxBufferGetCount(void) { return buffer_count[RxIrq]; } - - /** - * Function: txBufferGetSize - * - * Returns the current size of the TX buffer - * - * @ingroup API - * @return The length iof the TX buffer in bytes - */ - int txBufferGetSize(int size) { return buffer_size[TxIrq]; } - - /** - * Function: rxBufferGetSize - * - * Returns the current size of the RX buffer - * - * @ingroup API - * @return The length iof the RX buffer in bytes - */ - int rxBufferGetSize(int size) { return buffer_size[RxIrq]; } - - /** - * Function: txBufferFull - * - * Is the TX buffer full? - * - * @ingroup API - * @return true if the TX buffer is full, otherwise false - */ - bool txBufferFull(void); - - /** - * Function: rxBufferFull - * - * Is the RX buffer full? - * - * @ingroup API - * @return true if the RX buffer is full, otherwise false - */ - bool rxBufferFull(void); - - /** - * Function: txBufferEmpty - * - * Is the TX buffer empty? - * - * @ingroup API - * @return true if the TX buffer is empty, otherwise false - */ - bool txBufferEmpty(void); - - /** - * Function: rxBufferEmpty - * - * Is the RX buffer empty? - * - * @ingroup API - * @return true if the RX buffer is empty, otherwise false - */ - bool rxBufferEmpty(void); - - /** - * Function: txBufferSetSize - * - * Change the TX buffer size. - * - * @see Result - * @ingroup API - * @param size The new TX buffer size in bytes. - * @param m Perform a memory sanity check. Errs the Mbed if memory alloc fails. - * @return Result Ok on success. - */ - int txBufferSetSize(int size, bool m) { return resizeBuffer(size, TxIrq, m); } - - /** - * Function: rxBufferSetSize - * - * Change the RX buffer size. - * - * @see Result - * @ingroup API - * @param size The new RX buffer size in bytes. - * @param m Perform a memory sanity check. Errs the Mbed if memory alloc fails. - * @return Result Ok on success. - */ - int rxBufferSetSize(int size, bool m) { return resizeBuffer(size, RxIrq, m); } - - /** - * Function: txBufferSetSize - * - * Change the TX buffer size. - * Always performs a memory sanity check, halting the Mbed on failure. - * - * @see Result - * @ingroup API - * @param size The new TX buffer size in bytes. - * @return Result Ok on success. - */ - int txBufferSetSize(int size) { return resizeBuffer(size, TxIrq, true); } - - /** - * Function: rxBufferSetSize - * - * Change the RX buffer size. - * Always performs a memory sanity check, halting the Mbed on failure. - * - * @see Result - * @ingroup API - * @param size The new RX buffer size in bytes. - * @return Result Ok on success. - */ - int rxBufferSetSize(int size) { return resizeBuffer(size, RxIrq, true); } - - /** - * Function: txBufferFlush - * - * Remove all bytes from the TX buffer. - * @ingroup API - */ - void txBufferFlush(void) { flushBuffer(TxIrq); } - - /** - * Function: rxBufferFlush - * - * Remove all bytes from the RX buffer. - * @ingroup API - */ - void rxBufferFlush(void) { flushBuffer(RxIrq); } - - /** - * Function: getcNb - * - * Like getc() but is non-blocking. If no bytes are in the RX buffer this - * function returns Result::NoChar (-1) - * - * @ingroup API - * @return A byte from the RX buffer or Result::NoChar (-1) if bufer empty. - */ - int getcNb() { return __getc(false); } - - /** - * Function: getc - * - * Overloaded version of Serial::getc() - * - * This function blocks (if the RX buffer is empty the function will wait for a - * character to arrive and then return that character). - * - * @ingroup API - * @return A byte from the RX buffer - */ - int getc() { return __getc(true); } - - /** - * Function: txGetLastChar - * - * Rteurn the last byte to pass through the TX interrupt handler. - * - * @ingroup MISC - * @return The byte - */ - char txGetLastChar(void) { return txc; } - - /** - * Function: rxGetLastChar - * - * Return the last byte to pass through the RX interrupt handler. - * - * @ingroup MISC - * @return The byte - */ - char rxGetLastChar(void) { return rxc; } - - /** - * Function: txIsBusy - * - * If the Uart is still actively sending characters this - * function will return true. - * - * @ingroup API - * @return bool - */ - bool txIsBusy(void); - - /** - * Function: autoDetectChar - * - * Set the char that, if seen incoming, invokes the AutoDetectChar callback. - * - * @ingroup API - * @param int c The character to detect. - */ - void autoDetectChar(char c) { auto_detect_char = c; } - - /** - * Function: move - * - * Move contents of RX buffer to external buffer. Stops if "end" detected. - * - * @ingroup API - * @param char *s The destination buffer address - * @param int max The maximum number of chars to move. - * @param char end If this char is detected stop moving. - */ - int move(char *s, int max, char end) { - int counter = 0; - char c; - while(readable()) { - c = getc(); - if (c == end) break; - *(s++) = c; - counter++; - if (counter == max) break; - } - return counter; - } - - /** - * Function: move (overloaded) - * - * Move contents of RX buffer to external buffer. Stops if auto_detect_char detected. - * - * @ingroup API - * @param int max The maximum number of chars to move. - * @param char *s The destination buffer address - */ - int move(char *s, int max) { - return move(s, max, auto_detect_char); - } - - #if 0 // Inhereted from Serial/Stream, for documentation only - /** - * Function: putc - * - * Write a character - * Inhereted from Serial/Stream - * - * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.putc - * @ingroup API - * @param c The character to write to the serial port - */ - int putc(int c); - #endif - - #if 0 // Inhereted from Serial/Stream, for documentation only - /** - * Function: printf - * - * Write a formated string - * Inhereted from Serial/Stream - * - * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.printf - * @ingroup API - * @param format A printf-style format string, followed by the variables to use in formating the string. - */ - int printf(const char* format, ...); - #endif - - #if 0 // Inhereted from Serial/Stream, for documentation only - /** - * Function: scanf - * - * Read a formated string - * Inhereted from Serial/Stream - * - * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.scanf - * @ingroup API - * @param format - A scanf-style format string, followed by the pointers to variables to store the results. - */ - int scanf(const char* format, ...); - #endif - -protected: - /** - * Used to pass information to callbacks. - * @ingroup INTERNALS - */ - MODSERIAL_IRQ_INFO callbackInfo; - - /** - * Remove the last char placed into the rx buffer. - * This is an operation that can only be performed - * by an rxCallback function. To protect the buffers - * this function is defined protected so that a - * regular application cannot call it directly. It - * can only be called by the public version within a - * MODSERIAL_IRQ_INFO class. - * @ingroup INTERNALS - * @return The byte removed from the buffer. - */ - int rxDiscardLastChar(void); - -private: - - /** - * A pointer to the UART peripheral base address being used. - * @ingroup INTERNALS - */ - void *_base; - - /** - * The last byte to pass through the TX IRQ handler. - * @ingroup INTERNALS - */ - volatile char txc; - - /** - * The last byte to pass through the RX IRQ handler. - * @ingroup INTERNALS - */ - volatile char rxc; - - /** - * Pointers to the TX and RX buffers. - * @ingroup INTERNALS - */ - volatile char *buffer[2]; - - /** - * Buffer in pointers. - * @ingroup INTERNALS - */ - volatile int buffer_in[2]; - - /** - * Buffer out pointers. - * @ingroup INTERNALS - */ - volatile int buffer_out[2]; - - /** - * Buffer lengths. - * @ingroup INTERNALS - */ - volatile int buffer_size[2]; - - /** - * Buffer content counters. - * @ingroup INTERNALS - */ - volatile int buffer_count[2]; - - /** - * Buffer overflow. - * @ingroup INTERNALS - */ - volatile int buffer_overflow[2]; - - /** - * Auto-detect character. - * @ingroup INTERNALS - */ - volatile char auto_detect_char; - - /** - * Callback system. - * @ingroup INTERNALS - */ - MODSERIAL_callback _isr[NumOfIrqTypes]; - - /** - * TX Interrupt Service Routine. - * @ingroup INTERNALS - */ - void isr_tx(bool doCallback); - - /** - * TX Interrupt Service Routine stub version. - * @ingroup INTERNALS - */ - void isr_tx(void) { isr_tx(true); } - - - /** - * RX Interrupt Service Routine. - * @ingroup INTERNALS - */ - void isr_rx(void); - - /** - * Disable the interrupts for this Uart. - * @ingroup INTERNALS - */ - void disableIrq(void); - - /** - * Enable the interrupts for this Uart. - * @ingroup INTERNALS - */ - void enableIrq(void); - - /** - * Get a character from the RX buffer - * @ingroup INTERNALS - * @param bool True to block (wait for input) - * @return A byte from the buffer. - */ - int __getc(bool); - - /** - * Put a character from the TX buffer - * @ingroup INTERNALS - * @param bool True to block (wait for space in the TX buffer if full) - * @return 0 on success - */ - int __putc(int c, bool); - - /** - * Function: _putc - * Overloaded virtual function. - */ - virtual int _putc(int c) { return __putc(c, true); } - - /** - * Function: _getc - * Overloaded virtual function. - */ - virtual int _getc() { return __getc(true); } - - /** - * Function: init - * Initialize the MODSERIAL object - * @ingroup INTERNALS - */ - void init(int txSize, int rxSize, PinName rx); - - /** - * Function: flushBuffer - * @ingroup INTERNALS - */ - void flushBuffer(IrqType type); - - /** - * Function: resizeBuffer - * @ingroup INTERNALS - */ - int resizeBuffer(int size, IrqType type = RxIrq, bool memory_check = true); - - /** - * Function: downSizeBuffer - * @ingroup INTERNALS - */ - int downSizeBuffer(int size, IrqType type, bool memory_check); - - /** - * Function: upSizeBuffer - * @ingroup INTERNALS - */ - int upSizeBuffer(int size, IrqType type, bool memory_check); - - /* - * If MODDMA is available the compile in code to handle sending - * an arbitary char buffer. Note, the parts before teh #ifdef - * are declared so that MODSERIAL can access then even if MODDMA - * isn't avaiable. Since MODDMA.h is only available at this point - * all DMA functionality must be declared inline in the class - * definition. - */ -public: - - int dmaSendChannel; - void *moddma_p; - -#ifdef MODDMA_H - - MODDMA_Config *config; - - /** - * Set the "void pointer" moddma_p to be a pointer to a - * MODDMA controller class instance. Used to manage the - * data transfer of DMA configurations. - * - * @ingroup API - * @param p A pointer to "the" instance of MODDMA. - */ - void MODDMA(MODDMA *p) { moddma_p = p; } - - /** - * Send a char buffer to the Uarts TX system - * using DMA. This blocks regular library - * sending. - * - * @param buffer A char buffer of bytes to send. - * @param len The length of the buffer to send. - * @param dmaChannel The DMA channel to use, defaults to 7 - * @return MODDMA::Status MODDMA::ok if all went ok - */ - int dmaSend(char *buffer, int len, int dmaChannel = 7) - { - if (moddma_p == (void *)NULL) return -2; - class MODDMA *dma = (class MODDMA *)moddma_p; - - dmaSendChannel = dmaChannel & 0x7; - - uint32_t conn = MODDMA::UART0_Tx; - switch(_serial.index) { - case 0: conn = MODDMA::UART0_Tx; break; - case 1: conn = MODDMA::UART1_Tx; break; - case 2: conn = MODDMA::UART2_Tx; break; - case 3: conn = MODDMA::UART3_Tx; break; - } - - config = new MODDMA_Config; - config - ->channelNum ( (MODDMA::CHANNELS)(dmaSendChannel & 0x7) ) - ->srcMemAddr ( (uint32_t) buffer ) - ->transferSize ( len ) - ->transferType ( MODDMA::m2p ) - ->dstConn ( conn ) - ->attach_tc ( this, &MODSERIAL::dmaSendCallback ) - ->attach_err ( this, &MODSERIAL::dmaSendCallback ) - ; // config end - - // Setup the configuration. - if (dma->Setup(config) == 0) { - return -1; - } - - //dma.Enable( MODDMA::Channel_0 ); - dma->Enable( config->channelNum() ); - return MODDMA::Ok; - } - - /** - * Attach a callback to the DMA completion. - * - * @ingroup API - * @param fptr A function pointer to call - * @return this - */ - void attach_dmaSendComplete(void (*fptr)(MODSERIAL_IRQ_INFO *)) { - _isrDmaSendComplete.attach(fptr); - } - - /** - * Attach a callback to the DMA completion. - * - * @ingroup API - * @param tptr A template pointer to the calling object - * @param mptr A method pointer within the object to call. - * @return this - */ - template<typename T> - void attach_dmaSendComplete(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *)) { - if((mptr != NULL) && (tptr != NULL)) { - _isrDmaSendComplete.attach(tptr, mptr); - } - } - - MODSERIAL_callback _isrDmaSendComplete; - -protected: - /** - * Callback for dmaSend(). - */ - void dmaSendCallback(void) - { - if (moddma_p == (void *)NULL) return; - class MODDMA *dma = (class MODDMA *)moddma_p; - - MODDMA_Config *config = dma->getConfig(); - dma->haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); - dma->Disable( (MODDMA::CHANNELS)config->channelNum() ); - if (dma->irqType() == MODDMA::TcIrq) dma->clearTcIrq(); - if (dma->irqType() == MODDMA::ErrIrq) dma->clearErrIrq(); - dmaSendChannel = -1; - _isrDmaSendComplete.call(&this->callbackInfo); - delete(config); - } - -#endif // MODDMA_H - -}; - -}; // namespace AjK ends - -using namespace AjK; - -#endif
--- a/Libs/MODSERIAL/MODSERIAL_IRQ_INFO.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - @file MODSERIAL_IRQ_INFO.cpp - @author Andy Kirkham -*/ - -#include "MODSERIAL.h" - -namespace AjK { - -int -MODSERIAL_IRQ_INFO::rxDiscardLastChar(void) -{ - if (!serial) return -1; - - return serial->rxDiscardLastChar(); -} - -}; // namespace AjK ends
--- a/Libs/MODSERIAL/PUTC.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODSERIAL.h" -#include "MACROS.h" - -namespace AjK { - -int -MODSERIAL::__putc(int c, bool block) { - - // If no buffer is in use fall back to standard TX FIFO usage. - // Note, we must block in this case and ignore bool "block" - // so as to maintain compat with Mbed Serial. - if (buffer[TxIrq] == (char *)NULL || buffer_size[TxIrq] == 0) { - while (! MODSERIAL_THR_HAS_SPACE) ; // Wait for space in the TX FIFO. - _THR = (uint32_t)c; - return 0; - } - - if ( MODSERIAL_THR_HAS_SPACE && MODSERIAL_TX_BUFFER_EMPTY && dmaSendChannel == -1 ) { - _THR = (uint32_t)c; - } - else { - if (block) { - uint32_t ier = _IER; _IER = 1; - while ( MODSERIAL_TX_BUFFER_FULL ) { // Blocks! - // If putc() is called from an ISR then we are stuffed - // because in an ISR no bytes from the TX buffer will - // get transferred to teh TX FIFOs while we block here. - // So, to work around this, instead of sitting in a - // loop waiting for space in the TX buffer (which will - // never happen in IRQ context), check to see if the - // TX FIFO has space available to move bytes from the - // TX buffer to TX FIFO to make space. The easiest way - // to do this is to poll the isr_tx() function while we - // are blocking. - isr_tx(false); - } - _IER = ier; - } - else if( MODSERIAL_TX_BUFFER_FULL ) { - buffer_overflow[TxIrq] = c; // Oh dear, no room in buffer. - _isr[TxOvIrq].call(&this->callbackInfo); - return -1; - } - _IER &= ~2; - buffer[TxIrq][buffer_in[TxIrq]] = c; - __disable_irq(); - buffer_count[TxIrq]++; - __enable_irq(); - buffer_in[TxIrq]++; - if (buffer_in[TxIrq] >= buffer_size[TxIrq]) { - buffer_in[TxIrq] = 0; - } - _IER |= 2; - } - - return 0; -} - -}; // namespace AjK ends
--- a/Libs/MODSERIAL/RESIZE.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODSERIAL.h" -#include "MACROS.h" - -namespace AjK { - -int -MODSERIAL::resizeBuffer(int size, IrqType type, bool memory_check) -{ - int rval = Ok; - - // If the requested size is the same as the current size there's nothing to do, - // just continue to use the same buffer as it's fine as it is. - if (buffer_size[type] == size) return rval; - - // Make sure the ISR cannot use the buffers while we are manipulating them. - disableIrq(); - - // If the requested buffer size is larger than the current size, - // attempt to create a new buffer and use it. - if (buffer_size[type] < size) { - rval = upSizeBuffer(size, type, memory_check); - } - else if (buffer_size[type] > size) { - rval = downSizeBuffer(size, type, memory_check); - } - - // Start the ISR system again with the new buffers. - enableIrq(); - - return rval; -} - -int -MODSERIAL::downSizeBuffer(int size, IrqType type, bool memory_check) -{ - if (size >= buffer_count[type]) { - return BufferOversize; - } - - char *s = (char *)malloc(size); - - if (s == (char *)NULL) { - if (memory_check) { - error("Failed to allocate memory for %s buffer", type == TxIrq ? "TX" : "RX"); - } - return NoMemory; - } - - int c, new_in = 0; - - do { - c = __getc(false); - if (c != -1) s[new_in++] = (char)c; - if (new_in >= size) new_in = 0; - } - while (c != -1); - - free((char *)buffer[type]); - buffer[type] = s; - buffer_in[type] = new_in; - buffer_out[type] = 0; - return Ok; -} - -int -MODSERIAL::upSizeBuffer(int size, IrqType type, bool memory_check) -{ - char *s = (char *)malloc(size); - - if (s == (char *)NULL) { - if (memory_check) { - error("Failed to allocate memory for %s buffer", type == TxIrq ? "TX" : "RX"); - } - return NoMemory; - } - - if (buffer_count[type] == 0) { // Current buffer empty? - free((char *)buffer[type]); - buffer[type] = s; - buffer_in[type] = 0; - buffer_out[type] = 0; - } - else { // Copy the current contents into the new buffer. - int c, new_in = 0; - do { - c = __getc(false); - if (c != -1) s[new_in++] = (char)c; - if (new_in >= size) new_in = 0; // Shouldn't happen, but be sure. - } - while (c != -1); - free((char *)buffer[type]); - buffer[type] = s; - buffer_in[type] = new_in; - buffer_out[type] = 0; - } - - buffer_size[type] = size; - return Ok; -} - -}; // namespace AjK ends
--- a/Libs/MODSERIAL/example1.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -#ifdef COMPILE_EXAMPLE1_CODE_MODSERIAL - -/* - * To run this test program, link p9 to p10 so the Serial loops - * back and receives characters it sends. - */ - -#include "mbed.h" -#include "MODSERIAL.h" - -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); -DigitalOut led4(LED4); - -MODSERIAL pc(USBTX, USBRX); - -/* - * As experiement, you can define MODSERIAL as show here and see what - * effects it has on the LEDs. - * - * MODSERIAL uart(TX_PIN, RX_PIN, 512); - * With this, the 512 characters sent can straight into the buffer - * vary quickly. This means LED1 is only on briefly as the TX buffer - * fills. - * - * MODSERIAL uart(TX_PIN, RX_PIN, 32); - * With this, the buffer is smaller than the default 256 bytes and - * therefore LED1 stays on much longer while the system waits for - * room in the TX buffer. - */ -MODSERIAL uart(TX_PIN, RX_PIN); - -// This function is called when a character goes from the TX buffer -// to the Uart THR FIFO register. -void txCallback(MODSERIAL_IRQ_INFO *q) { - led2 = !led2; -} - -// This function is called when TX buffer goes empty -void txEmpty(MODSERIAL_IRQ_INFO *q) { - led2 = 0; - pc.puts(" Done. "); -} - -// This function is called when a character goes into the RX buffer. -void rxCallback(MODSERIAL_IRQ_INFO *q) { - led3 = !led3; - pc.putc(uart.getc()); -} - -int main() { - int c = 'A'; - - // Ensure the baud rate for the PC "USB" serial is much - // higher than "uart" baud rate below. - pc.baud(PC_BAUD); - - // Use a deliberatly slow baud to fill up the TX buffer - uart.baud(1200); - - uart.attach(&txCallback, MODSERIAL::TxIrq); - uart.attach(&rxCallback, MODSERIAL::RxIrq); - uart.attach(&txEmpty, MODSERIAL::TxEmpty); - - // Loop sending characters. We send 512 - // which is twice the default TX/RX buffer size. - - led1 = 1; // Show start of sending with LED1. - - for (int loop = 0; loop < 512; loop++) { - uart.printf("%c", c); - c++; - if (c > 'Z') c = 'A'; - } - - led1 = 0; // Show the end of sending by switching off LED1. - - // End program. Flash LED4. Notice how LED 2 and 3 continue - // to flash for a short period while the interrupt system - // continues to send the characters left in the TX buffer. - - while(1) { - led4 = !led4; - wait(0.25); - } -} - -/* - * Notes. Here is the sort of output you can expect on your PC/Mac/Linux host - * machine that is connected to the "pc" USB serial port. - * - * ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV - * WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR - * STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN - * OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ - * KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF - * GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB - * CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ Done. R - * - * Of interest is that last "R" character after the system has said "Done." - * This comes from the fact that the TxEmpty callback is made when the TX buffer - * becomes empty. MODSERIAL makes use of the fact that the Uarts built into the - * LPC17xx device use a 16 byte FIFO on both RX and TX channels. This means that - * when the TxEmpty callback is made, the TX buffer is empty, but that just means - * the "last few characters" were written to the TX FIFO. So although the TX - * buffer has gone empty, the Uart's transmit system is still sending any remaining - * characters from it's TX FIFO. If you want to be truely sure all the characters - * you have sent have left the Mbed then call txIsBusy(); This function will - * return true if characters are still being sent. If it returns false after - * the Tx buffer is empty then all your characters have been sent. - * - * In a similar way, when characters are received into the RX FIFO, the entire - * FIFO contents is moved to the RX buffer, assuming there is room left in the - * RX buffer. If there is not, any remaining characters are left in the RX FIFO - * and will be moved to the RX buffer on the next interrupt or when the running - * program removes a character(s) from the RX buffer with the getc() method. - */ - -#endif
--- a/Libs/MODSERIAL/example2.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -/* - Copyright (c) 2011 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - @file example2.cpp - @purpose Demos a simple messaging system. - @version see ChangeLog.c - @date Jan 2011 - @author Andy Kirkham -*/ - -/* - This example demostrates a simple "messaging" system. You can use it with - a terminal program to test it out or write a cusom C#/C++/VB/etc program - to read and write messages to or from the Mbed. The default baud rate in - this example is 115200. - - In this example, the LEDs are controlled and pins p21 to p24 are set as - InterruptIn and send messages out when their value changes. - - To use, hook up the MBed USB and open your fav terminal. All messages - end with the \n character, don't forget to hit carriage return!. - As an example:- - - to switch on LED1 send LED1:1\n, off is LED1:0\n and toggle is LED1:2\n - to switch on LED2 send LED2:1\n, off is LED2:0\n and toggle is LED2:2\n - to switch on LED3 send LED3:1\n, off is LED3:0\n and toggle is LED3:2\n - to switch on LED4 send LED4:1\n, off is LED4:0\n and toggle is LED4:2\n - - When a pin change on p21 to p24 happens, a message is sent. As an example - when p21 goes low PIN21:0\n is sent, when goes high PIN21:1\n is sent. - - Note, the InterruptIn pins p21 to p24 are setup to have pullups. This means - they are high. To activate them use a wire to short the pin to 0volts. - - If you find that p21 to p24 sent a lot of on/off/on/off then it's probably - due to "bounce". If you are connecting a mechanical switch to a pin you - may prefer to use the PinDetect library rather than using InterruptIn. - @see http://mbed.org/users/AjK/libraries/PinDetect/latest - - One point you may notice. Incoming messages are processed via main()'s - while(1) loop whereas pin changes have their messages directly sent. - The reason for this is when MODSERIAL makes callbacks to your application - it is in "interrupt context". And one thing you want to avoid is spending - lots of CPU time in that context. So, the callback moves the message from - the input buffer to a local holding buffer and it then sets a bool flag - which tells main()'s while(1) loop to process that buffer. This means the - time spent doing the real incoming message handing is within your program - and not within MODSERIAL's interrupt context. So you may ask, why not do - the same for out going messages? Well, because MODSERIAL output buffers - all your sent content then sending chars is very fast. MODSERIAL handles - all the nitty gritty bits for you. You can just send. This example uses - puts() to send the message. If you can, always try and use sprintf()+puts() - rathe than printf(), printf() is known to often screw things up when used - within an interrupt context. Better still, just use puts() and do away - with any of the crappy ?printf() calls if possible. But I found the code - below to work fine even at 115200baud. - -*/ - - -#ifdef COMPILE_EXAMPLE1_CODE_MODSERIAL - -#include "mbed.h" -#include "MODSERIAL.h" - -#define MESSAGE_BUFFER_SIZE 32 - -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); -DigitalOut led4(LED4); - -InterruptIn P21(p21); -InterruptIn P22(p22); -InterruptIn P23(p23); -InterruptIn P24(p24); - -MODSERIAL messageSystem(USBTX, USBRX); - -char messageBufferIncoming[MESSAGE_BUFFER_SIZE]; -char messageBufferOutgoing[MESSAGE_BUFFER_SIZE]; -bool messageReceived; - -void messageReceive(MODSERIAL_IRQ_INFO *q) { - MODSERIAL *sys = q->serial; - sys->move(messageBufferIncoming, MESSAGE_BUFFER_SIZE); - messageReceived = true; - return 0; -} - -void messageProcess(void) { - if (!strncmp(messageBufferIncoming, "LED1:1", sizeof("LED1:1")-1)) led1 = 1; - else if (!strncmp(messageBufferIncoming, "LED1:0", sizeof("LED1:0")-1)) led1 = 0; - else if (!strncmp(messageBufferIncoming, "LED1:2", sizeof("LED1:2")-1)) led1 = !led1; - - else if (!strncmp(messageBufferIncoming, "LED2:1", sizeof("LED2:1")-1)) led2 = 1; - else if (!strncmp(messageBufferIncoming, "LED2:0", sizeof("LED2:0")-1)) led2 = 0; - else if (!strncmp(messageBufferIncoming, "LED2:2", sizeof("LED2:2")-1)) led2 = !led2; - - else if (!strncmp(messageBufferIncoming, "LED3:1", sizeof("LED3:1")-1)) led3 = 1; - else if (!strncmp(messageBufferIncoming, "LED3:0", sizeof("LED3:0")-1)) led3 = 0; - else if (!strncmp(messageBufferIncoming, "LED3:2", sizeof("LED3:2")-1)) led3 = !led3; - - else if (!strncmp(messageBufferIncoming, "LED4:1", sizeof("LED4:1")-1)) led4 = 1; - else if (!strncmp(messageBufferIncoming, "LED4:0", sizeof("LED4:0")-1)) led4 = 0; - else if (!strncmp(messageBufferIncoming, "LED4:2", sizeof("LED4:2")-1)) led4 = !led4; - - messageReceived = false; -} - -#define PIN_MESSAGE_SEND(x,y) \ - sprintf(messageBufferOutgoing,"PIN%02d:%d\n",x,y);\ - messageSystem.puts(messageBufferOutgoing); - -void pin21Rise(void) { PIN_MESSAGE_SEND(21, 1); } -void pin21Fall(void) { PIN_MESSAGE_SEND(21, 0); } -void pin22Rise(void) { PIN_MESSAGE_SEND(22, 1); } -void pin22Fall(void) { PIN_MESSAGE_SEND(22, 0); } -void pin23Rise(void) { PIN_MESSAGE_SEND(23, 1); } -void pin23Fall(void) { PIN_MESSAGE_SEND(23, 0); } -void pin24Rise(void) { PIN_MESSAGE_SEND(24, 1); } -void pin24Fall(void) { PIN_MESSAGE_SEND(24, 0); } - -int main() { - - messageReceived = false; - messageSystem.baud(115200); - messageSystem.attach(&messageReceive, MODSERIAL::RxAutoDetect); - messageSystem.autoDetectChar('\n'); - - // Enable pullup resistors on pins. - P21.mode(PullUp); P22.mode(PullUp); P23.mode(PullUp); P24.mode(PullUp); - - // Fix Mbed library bug, see http://mbed.org/forum/bugs-suggestions/topic/1498 - LPC_GPIOINT->IO2IntClr = (1UL << 5) | (1UL << 4) | (1UL << 3) | (1UL << 2); - - // Attach InterruptIn pin callbacks. - P21.rise(&pin21Rise); P21.fall(&pin21Fall); - P22.rise(&pin22Rise); P22.fall(&pin22Fall); - P23.rise(&pin23Rise); P23.fall(&pin23Fall); - P24.rise(&pin24Rise); P24.fall(&pin24Fall); - - while(1) { - // Process incoming messages. - if (messageReceived) messageProcess(); - } -} - -#endif
--- a/Libs/MODSERIAL/example3a.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - Copyright (c) 2011 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - @file example3.cpp - @purpose Demos a simple filter. - @version see ChangeLog.c - @author Andy Kirkham -*/ - -/* - This example shows how to use the new callback system. In the old system - Mbed's FunctionPointer[1] type was used to store abd make calls to callbacks. - However, that limits the callback function prototype to void func(void); - which means we cannot pass parameters. - - This latest version of MODSERIAL now uses its own callback object. This allows - the passing of a pointer to a class that holds information about the MODSERIAL - object making the callback. As of version 1.18 one critcal piece of information - is passed, a pointer to the MODSERIAL object. This allows callbacks to use the - MODSERIAL functions and data. - - Additionally, since MODSERIAL and the callback parameter class MODSERIAL_IRQ_INFO - are friends, MODSERIAL_IRQ_INFO can access the protected functions of MODSERIAL. - This is used to ensure functions that can only be called during a callback - can be invoked from a callback. - - [1] http://mbed.org/projects/libraries/svn/mbed/trunk/FunctionPointer.h -*/ - -#ifdef COMPILE_EXAMPLE3_CODE_MODSERIAL - -#include "mbed.h" -#include "MODSERIAL.h" - -DigitalOut led1(LED1); - -MODSERIAL pc(USBTX, USBRX); - -// The following callback is defined in example3b.cpp -//! @see example3b.cpp -void rxCallback(MODSERIAL_IRQ_INFO *info); - -int main() { - - int life_counter = 0; - - pc.baud(115200); - - pc.attach(&rxCallback, MODSERIAL::RxIrq); - - while(1) { - // Echo back any chars we get except 'A' which is filtered by the rxCallback. - if (pc.readable()) { - pc.putc(pc.getc()); - } - - // Toggle LED1 every so often to show we are alive. - if (life_counter++ == 1000000) { - life_counter = 0; - led1 = !led1; - } - } -} - -#endif
--- a/Libs/MODSERIAL/example3b.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - Copyright (c) 2011 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - @file example3b.cpp - @purpose Demos a simple filter. - @version see ChangeLog.c - @author Andy Kirkham -*/ - -/* - This example shows how to use the new callback system. In the old system - Mbed's FunctionPointer[1] type was used to store abd make calls to callbacks. - However, that limits the callback function prototype to void func(void); - which means we cannot pass parameters. - - This latest version of MODSERIAL now uses its own callback object. This allows - the passing of a pointer to a class that holds information about the MODSERIAL - object making the callback. As of version 1.18 one critcal piece of information - is passed, a pointer to the MODSERIAL object. This allows callbacks to use the - MODSERIAL functions and data. - - Additionally, since MODSERIAL and the callback parameter class MODSERIAL_IRQ_INFO - are friends, MODSERIAL_IRQ_INFO can access the protected functions of MODSERIAL. - This is used to ensure functions that can only be called during a callback - can be invoked from a callback. - - [1] http://mbed.org/projects/libraries/svn/mbed/trunk/FunctionPointer.h -*/ - - -#ifdef COMPILE_EXAMPLE3_CODE_MODSERIAL - -#include "mbed.h" -#include "MODSERIAL.h" - -void rxCallback(MODSERIAL_IRQ_INFO *info) { - - // Get the pointer to our MODSERIAL object that invoked this callback. - MODSERIAL *pc = info->serial; - - // info->serial points at the MODSERIAL instance so we can use it to call - // any of the public MODSERIAL functions that are normally available. So - // there's now no need to use the global version (pc in our case) inside - // callback functions. - char c = pc->rxGetLastChar(); // Where local pc variable is a pointer to the global MODSERIAL pc object. - - // The following is rather daft but demos the point. - // Don't allow the letter "A" go into the RX buffer. - // Basically acts as a filter to remove the letter "A" - // if it goes into the RX buffer. - if (c == 'A') { - // Note, we call the MODSERIAL_IRQ_INFO::rxDiscardLastChar() public function which - // is permitted access to the protected version of MODSERIAL::rxDiscardLastChar() - // within MODSERIAL (because they are friends). This ensures rxDiscardLastChar() - // can only be called within an rxCallback function. - info->rxDiscardLastChar(); - } -} - -#endif
--- a/Libs/MODSERIAL/example_dma.cpp Sun Nov 16 02:43:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -#ifdef COMPILE_EXAMPLE_CODE_MODSERIAL_MODDMA - -/* - * To run this test program, link p9 to p10 so the Serial loops - * back and receives characters it sends. - */ - -#include "mbed.h" - -/* Note, this example requires that you also import into the Mbed - compiler the MODDMA project as well as MODSERIAL - http://mbed.org/users/AjK/libraries/MODDMA/latest - MODDMA.h MUST come before MODSERIAL.h */ -#include "MODDMA.h" // <--- Declare first -#include "MODSERIAL.h" // Flollowed by MODSERIAL - -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); -DigitalOut led4(LED4); - -MODSERIAL pc(USBTX, USBRX); - -/* - * As experiement, you can define MODSERIAL as show here and see what - * effects it has on the LEDs. - * - * MODSERIAL uart(TX_PIN, RX_PIN, 512); - * With this, the 512 characters sent can straight into the buffer - * vary quickly. This means LED1 is only on briefly as the TX buffer - * fills. - * - * MODSERIAL uart(TX_PIN, RX_PIN, 32); - * With this, the buffer is smaller than the default 256 bytes and - * therefore LED1 stays on much longer while the system waits for - * room in the TX buffer. - */ -MODSERIAL uart(TX_PIN, RX_PIN); - -MODDMA dma; - -// This function is called when a character goes from the TX buffer -// to the Uart THR FIFO register. -void txCallback(void) { - led2 = !led2; -} - -// This function is called when TX buffer goes empty -void txEmpty(void) { - led2 = 0; - pc.puts(" Done. "); -} - -void dmaComplete(void) { - led1 = 1; -} - -// This function is called when a character goes into the RX buffer. -void rxCallback(void) { - led3 = !led3; - pc.putc(uart.getc()); -} - -int main() { - char s1[] = " *DMA* *DMA* *DMA* *DMA* *DMA* *DMA* *DMA* "; - int c = 'A'; - - // Tell MODSERIAL where the MODDMA controller is. - pc.MODDMA( &dma ); - - // Ensure the baud rate for the PC "USB" serial is much - // higher than "uart" baud rate below. - pc.baud( PC_BAUD ); - - // Use a deliberatly slow baud to fill up the TX buffer - uart.baud(1200); - - uart.attach( &txCallback, MODSERIAL::TxIrq ); - uart.attach( &rxCallback, MODSERIAL::RxIrq ); - uart.attach( &txEmpty, MODSERIAL::TxEmpty ); - - // Loop sending characters. We send 512 - // which is twice the default TX/RX buffer size. - - led1 = 0; - - // Send the buffer s using DMA channel 7 - pc.attach_dmaSendComplete( &dmaComplete ); - pc.dmaSend( s1, sizeof(s1), MODDMA::Channel_7 ); - - for (int loop = 0; loop < 512; loop++) { - uart.printf("%c", c); - c++; - if (c > 'Z') c = 'A'; - } - - led1 = 0; // Show the end of sending by switching off LED1. - - // End program. Flash LED4. Notice how LED 2 and 3 continue - // to flash for a short period while the interrupt system - // continues to send the characters left in the TX buffer. - - while(1) { - led4 = !led4; - wait(0.25); - } -} - -/* - * Notes. Here is the sort of output you can expect on your PC/Mac/Linux host - * machine that is connected to the "pc" USB serial port. - * - * *DMA* *DMA* *DMA* *DMA* *DMA* *DMA* *DMA* ABCDEFGHIJKLMNOPQRSTUVWXYZABCDE - * FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA - * BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW - * XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS - * TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO - * PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK - * LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG - * HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ Done. R - * - * Note how the DMA blocks the TX buffer sending under standard interrupt control. - * Not until the DMA transfer is complete will "normal" buffered TX sending resume. - * - * Of interest is that last "R" character after the system has said "Done." - * This comes from the fact that the TxEmpty callback is made when the TX buffer - * becomes empty. MODSERIAL makes use of the fact that the Uarts built into the - * LPC17xx device use a 16 byte FIFO on both RX and TX channels. This means that - * when the TxEmpty callback is made, the TX buffer is empty, but that just means - * the "last few characters" were written to the TX FIFO. So although the TX - * buffer has gone empty, the Uart's transmit system is still sending any remaining - * characters from it's TX FIFO. If you want to be truely sure all the characters - * you have sent have left the Mbed then call txIsBusy(); This function will - * return true if characters are still being sent. If it returns false after - * the Tx buffer is empty then all your characters have been sent. - * - * In a similar way, when characters are received into the RX FIFO, the entire - * FIFO contents is moved to the RX buffer, assuming there is room left in the - * RX buffer. If there is not, any remaining characters are left in the RX FIFO - * and will be moved to the RX buffer on the next interrupt or when the running - * program removes a character(s) from the RX buffer with the getc() method. - */ - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Libs/XbeeManager/CAN-xbee/CAN-xbee.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -0,0 +1,120 @@ +#include "CAN-xbee.h" + +CANxbee::CANxbee(PinName tx, PinName rx, int _baud, int txSize, int rxSize) : serial(tx, rx, txSize, rxSize) { + serial.baud(_baud); + rx_i = 0; + rxBuff[0] = 0; + building = false; +} + +// Send a CAN message, first reformat it into a char array, then send over Xbees +bool CANxbee::send(CANMessage &msg) { + char buff[14]; // Build the string-ified CAN message here + int size; + + buff[0] = 'C'; + int i; + if (msg.format == 0) { // Standard, 11-bit ID + buff[1] = (0 << 0) | (msg.type << 1) | ((msg.len & 0xf) << 2); + buff[2] = msg.id & 0xFF; // Lower byte of ID + buff[3] = (msg.id & 0x7FF) >> 8; + for (i = 0; (i < msg.len) && (i < 8); i++) { + buff[i+4] = msg.data[i]; // Get data bytes + } + buff[i+4] = '\n'; // Terminate message + size = i+4+1; + + } else if (msg.format == 1) { // Extended, 29-bit ID + buff[1] = (1 << 0) | (msg.type << 1) | ((msg.len & 0xf) << 2); + buff[2] = msg.id & 0x000000FF; // Lower byte of ID + buff[3] = msg.id & 0x0000FF00 >> 8; + buff[4] = msg.id & 0x00FF0000 >> 16; + buff[5] = msg.id & 0x1F000000 >> 24; + for (i = 0; (i < msg.len) && (i < 8); i++) { + buff[i+6] = msg.data[i]; // Get data bytes + } + buff[i+6] = '\n'; // Terminate message + size = i+6+1; + } else return false; // Bad message + + bool success=false; + + // Begin thread-safe section + __disable_irq(); + + // Check if enough spaces in buffer + if ((serial.txBufferGetSize(0) - serial.txBufferGetCount()) >= size) { + for (int i = 0; i < size; i++) serial.putc(buff[i]); // Send the message out + success = true; + } + + // End thread-safe section + __enable_irq(); + + return success; +} + +// Continuously call this function in main program, when it returns true, it holds a newly received CAN message that came via Xbee +bool CANxbee::receive(CANMessage &msg) { + int newChar = serial.getcNb(); + if (newChar == -1) return false; // No new char + char c = newChar & 0xFF; // Cast to char + bool process=false; + + char len=0; + // Listen for a 'C', start of new message + if (c == 'C' && !building) { + rxBuff[rx_i] = 'C'; + rx_i++; + building = true; // Now building a string + return false; + } + // Keep building a new message until too big or encounter '\n' + if (building) { + rxBuff[rx_i] = c; + rx_i++; + if (c == '\n') { // Newline! process this string + process = true; + building = false; // Reset to keep capturing on next call + len = rx_i; + rx_i = 0; + } + else if (rx_i >= sizeof(rxBuff)) { // Too big, bad string + rx_i = 0; + building = false; + return false; + } + } + if (!process) return false; + + // A string is ready, process it here + if (rxBuff[0] != 'C') return false; // No start char, not valid + + // Extract the data from the header byte + bool extended = rxBuff[1] & 1; + bool rtr = rxBuff[1] & 2; + char DLC = rxBuff[1] >> 2; + int id=0; + if (DLC > 8) return false; // Bad DLC + if (!extended) { // Standard ID + if (len > 12 || len < 5) return false; // Too big/too small for standard size + if (rxBuff[3] & 0x7 != rxBuff[3]) return false; // Last byte of ID bad + if (len != 5 + DLC) return false; // Improper number of bytes + id = rxBuff[2] | (rxBuff[3] << 8); // Build the ID + for (int i = 0; i < DLC; i++) msg.data[i] = rxBuff[i+4]; // Build the data array + + } else { // Extended ID + if (len > 14 || len < 7) return false; // Too big/too small for extended size + if (rxBuff[5] & 0x1F != rxBuff[5]) return false; // Last byte of ID bad + if (len != 7 + DLC) return false; // Improper number of bytes + id = rxBuff[2] | (rxBuff[3] << 8) | (rxBuff[4] << 16) | (rxBuff[5] << 24); // Build the ID + for (int i = 0; i < DLC; i++) msg.data[i] = rxBuff[i+6]; // Build the data array + } + msg.id = id; + msg.len = DLC; + if (rtr) msg.type = CANRemote; + else msg.type = CANData; + if (extended) msg.format = CANExtended; + else msg.format = CANStandard; + return true; // Successfully parsed, passed all checks, arguement was updated +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Libs/XbeeManager/CAN-xbee/CAN-xbee.h Tue Jan 06 20:45:26 2015 +0000 @@ -0,0 +1,32 @@ +#ifndef CAN_XBEE_H +#define CAN_XBEE_H + +#include "mbed.h" +#include "MODSERIAL.h" + +// The string format of a CAN message shall be: +// char0: Letter 'C' - start of a CAN message +// char1: message type = (extended?1:0 << 0) | (RTR?1:0 << 1) | (DLC << 2) +// char1: ID lower byte +// char2: ID upper byte +// char3-10: data bytes (lowest first) +// lastChar: \n - newline = end of message +// +// Extended ID message is the same but with more ID bytes. +// RTR messages show up as empty messages (no data, DLC=0) but are otherwise indistinguishable. + +class CANxbee { +public: + CANxbee(PinName tx, PinName rx, int baud, int txSize, int rxSize); + + bool send(CANMessage &msg); // Send a CANMessage object over the xbee (first converts to serial) + bool receive(CANMessage &msg); // Receive a CANMessage object over the xbee (converts from serial message to CAN) + +private: + MODSERIAL serial; + char rxBuff[14]; + int rx_i; + bool building; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Libs/XbeeManager/XbeeManager.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -0,0 +1,53 @@ +#include "XbeeManager.h" + +XbeeManager::XbeeManager(CANxbee* _x1, CANxbee* _x2) +{ + x1 = _x1; + x2 = _x2; + alternate = false; + extraAvail = false; + counterX1in = 0; + counterX2in = 0; + counterX1out = 0; + counterX2out = 0; +} + +bool XbeeManager::send(CANMessage &msg) +{ + alternate = !alternate; + if (alternate) { + if (x1->send(msg)) { + counterX1out++; + return true; + } + } else { + if (x2->send(msg)) { + counterX2out++; + return true; + } + } + return false; +} + +bool XbeeManager::receive(CANMessage &msg) +{ + if (extraAvail) { + extraAvail = false; + memcpy((void*)&msg, (void*)&extra, sizeof(CANMessage)); + counterX2in++; + return true; + } + if (x1->receive(msg)) { + if (x2->receive(extra)) { + extraAvail = true; + } + counterX1in++; + return true; + } else { + if (x2->receive(msg)) { + counterX2in++; + return true; + } + } + return false; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Libs/XbeeManager/XbeeManager.h Tue Jan 06 20:45:26 2015 +0000 @@ -0,0 +1,25 @@ +#ifndef XBEE_MANAGER_H +#define XBEE_MANAGER_H + +#include "mbed.h" +#include "CAN-xbee.h" + +class XbeeManager { +public: + XbeeManager(CANxbee* x1, CANxbee* x2); + bool send(CANMessage &msg); + bool receive(CANMessage &msg); + unsigned int counterX1in; + unsigned int counterX2in; + unsigned int counterX1out; + unsigned int counterX2out; + +private: + bool alternate; + CANxbee* x1; + CANxbee* x2; + CANMessage extra; + bool extraAvail; +}; + +#endif \ No newline at end of file
--- a/Libs/mbed-rtos.lib Sun Nov 16 02:43:58 2014 +0000 +++ b/Libs/mbed-rtos.lib Tue Jan 06 20:45:26 2015 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/users/mbed_official/code/mbed-rtos/#a3452b867ec3 +http://developer.mbed.org/users/mbed_official/code/mbed-rtos/#13a25134ac60
--- a/Libs/xbeeRelay/XbeeRelay.cpp Sun Nov 16 02:43:58 2014 +0000 +++ b/Libs/xbeeRelay/XbeeRelay.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -1,7 +1,7 @@ #include "XbeeRelay.h" #include "mbed.h" -#include "MODDMA.h" -#include "MODSERIAL.h" +//#include "MODDMA.h" +//#include "MODSERIAL.h" #include "PERMessage.h" #define MOTORCONID 0x181 @@ -17,8 +17,8 @@ XbeeRelay::XbeeRelay() : Xbee_e1(p9,p10), Xbee_e2(p13,p14), counter(0) { Xbee_e1.baud(250000); Xbee_e2.baud(250000); - Xbee_e1.MODDMA(&dma); - Xbee_e2.MODDMA(&dma); + // Xbee_e1.MODDMA(&dma); + //Xbee_e2.MODDMA(&dma); } bool XbeeRelay::receive(CANMessage cm) { @@ -52,13 +52,13 @@ char dataarr[pm.getLength() + 2]; pm.getDataArray(dataarr); - if (!dma.Enabled(DMA_CHANNEL_XBEE_1)) { - Xbee_e1.dmaSend(dataarr, sizeof(dataarr), DMA_CHANNEL_XBEE_1); + /* if (!dma.Enabled(DMA_CHANNEL_XBEE_1)) { + // Xbee_e1.dmaSend(dataarr, sizeof(dataarr), DMA_CHANNEL_XBEE_1); return true; } else if (!dma.Enabled(DMA_CHANNEL_XBEE_2)) { - Xbee_e2.dmaSend(dataarr, sizeof(dataarr), DMA_CHANNEL_XBEE_2); + // Xbee_e2.dmaSend(dataarr, sizeof(dataarr), DMA_CHANNEL_XBEE_2); return true; } - + */ return false; } \ No newline at end of file
--- a/Libs/xbeeRelay/XbeeRelay.h Sun Nov 16 02:43:58 2014 +0000 +++ b/Libs/xbeeRelay/XbeeRelay.h Tue Jan 06 20:45:26 2015 +0000 @@ -3,7 +3,7 @@ #define XBEERELAY #include "mbed.h" -#include "MODDMA.h" +//#include "MODDMA.h" #include "MODSERIAL.h" #include "PERMessage.h" @@ -25,7 +25,7 @@ MODSERIAL Xbee_e1; MODSERIAL Xbee_e2; unsigned int counter; - MODDMA dma; + //MODDMA dma; CANMessage cm; PERMessage pm; };
--- a/main.cpp Sun Nov 16 02:43:58 2014 +0000 +++ b/main.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -4,32 +4,49 @@ #include "serviceCAN.h" int main() { - wdt.kick(0.11); // Kick the watchdog timer, set the timeout to 110ms - pc.baud(921600); - pc.printf("\r\n\r\nSys Mgmt Reset\r\n"); - can.mode(FIFO); // Use FIFO mode - NVIC_SetPriority(TIMER3_IRQn, 2); // Decrease timer3 priority (mbed timer, rtos) - NVIC_SetPriority(UART0_IRQn, 1); // Decrease serial priority to give CAN higher priority + wdt.kick(); // Kick the watchdog timer + pc.baud(BAUD); + pc.format(8, SerialBase::None, 2); // 2 Stop bits, reduce bad serial packets + can.mode(FIFO); + DigitalOut led1(LED1); + + bool normalReset = true; // Did a watchdog reset occur since last power cycle? if (wdt.checkFlag()) { + wdt.clearFlag(); // Clear flag data.watchdogReset = true; - pc.printf("Watchdog Reset\r\n"); + pc.printf("Sys Mgmt Watchdog Reset\r\n"); + led1=1; + normalReset=false; } - + // Did a brownout reset occur since last power cycle? + if (LPC_SC->RSID & (1<<3)) { + LPC_SC->RSID = (1<<3); // Clear flag + pc.printf("Sys Mgmt Brownout Reset\r\n"); + normalReset=false; + } + // Print normal reset string + if (normalReset) pc.printf("Sys Mgmt Reset\r\n"); + // Start the 10Hz data thread - Thread gather_10Hz(runTime::thread_gather_10Hz, 0, osPriorityHigh); + // Thread gather(runTime::thread_gather, 0, osPriorityHigh); // Start the 100Hz data timer (more time critical than thread) - Thread gather_100Hz(runTime::thread_gather_100Hz, 0, osPriorityRealtime); - + //RtosTimer sample(runTime::thread_sample, osTimerPeriodic); + //sample.start(FAST_LOOP*1000); + // Start the serial, CAN threads Thread serial_out(outDiagnostics::thread_serialOut, 0, osPriorityAboveNormal, 6000); // Allocate 6kB RAM stack - Thread can_out(outDiagnostics::thread_canOut, 0, osPriorityAboveNormal); // Allocate 256B RAM stack + //Thread can_out(outDiagnostics::thread_canOut, 0, osPriorityAboveNormal); // Allocate 256B RAM stack + + wdt.kick(WDT_TIME); // Startup complete, normal timeout // Background task while(1) { // Service CAN and Xbee logic - if (canbus::serviceCAN()); + //if (canbus::serviceCAN()); + //canbus::receiveMsgXbee(); + wdt.kick(); } } \ No newline at end of file
--- a/outDiagnostics/outDiagnostics.cpp Sun Nov 16 02:43:58 2014 +0000 +++ b/outDiagnostics/outDiagnostics.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -1,5 +1,4 @@ #include "outDiagnostics.h" -#include "CAN_TxIDs.h" // Macros for working with the string #define ADD_LINE len+=sprintf(buff+len,"%s\r\n",line); // Add newlines, add it to the working buffer @@ -76,11 +75,11 @@ else sprintf(temp, "%s is OPEN.", switchNames[switches-1]); ADD_SPRINTF_LINE - /* padCenter(line, max_charsPerLine-2, " ", ' '); ADD_LINE // Generate blank line + padCenter(line, max_charsPerLine-2, " ", ' '); ADD_LINE // Generate blank line padCenter(line, max_charsPerLine-2, " Telemetry ", '*'); ADD_LINE - sprintf(temp, "Channel 1: MessagesIn: %d MessagesOut: %d", data.xbee1MessagesIn, data.xbee1MessagesOut); ADD_SPRINTF_LINE - sprintf(temp, "Channel 2: MessagesIn: %d MessagesOut: %d", data.xbee2MessagesIn, data.xbee2MessagesOut); ADD_SPRINTF_LINE -*/ + sprintf(temp, "Channel 1: MessagesIn: %d MessagesOut: %d", xbeeRelay.counterX1in, xbeeRelay.counterX1out); ADD_SPRINTF_LINE + sprintf(temp, "Channel 2: MessagesIn: %d MessagesOut: %d", xbeeRelay.counterX2in, xbeeRelay.counterX2out); ADD_SPRINTF_LINE + padCenter(line, max_charsPerLine-2, " ", ' '); ADD_LINE // Generate blank line padCenter(line, max_charsPerLine-2, " Miscellaneous ", '*'); ADD_LINE sprintf(temp, "Temp: %5.1fC OverTemp: %s canFault: %s WatchdogReset: %s ErrorFrame: 0x%x", data.internalTemp, BOOL(data.internalOverTemp), BOOL(data.canFault), BOOL(data.watchdogReset), data.errorFrame); ADD_SPRINTF_LINE @@ -106,7 +105,7 @@ msg.len = sizeof(T); memcpy(&msg.data[0], (void*)&dat, sizeof(T)); if (!can.txWrite(msg)) data.canFault = true; - xbee.receive(msg); + xbeeRelay.send(msg); } void outDiagnostics::thread_canOut(void const *args) { @@ -120,18 +119,18 @@ // Xbee1 Counter msg.id = SYS_XBEE1_ID; msg.len = 2*sizeof(int); - memcpy(&msg.data[0], (void*)&data.xbee1MessagesIn, sizeof(int)); - memcpy(&msg.data[4], (void*)&data.xbee1MessagesOut, sizeof(int)); + memcpy(&msg.data[0], (void*)&xbeeRelay.counterX1in, sizeof(int)); + memcpy(&msg.data[4], (void*)&xbeeRelay.counterX1out, sizeof(int)); if (!can.txWrite(msg)) data.canFault = true; - xbee.receive(msg); + xbeeRelay.send(msg); // Xbee2 Counter msg.id = SYS_XBEE2_ID; msg.len = 2*sizeof(int); - memcpy(&msg.data[0], (void*)&data.xbee2MessagesIn, sizeof(int)); - memcpy(&msg.data[4], (void*)&data.xbee2MessagesOut, sizeof(int)); + memcpy(&msg.data[0], (void*)&xbeeRelay.counterX2in, sizeof(int)); + memcpy(&msg.data[4], (void*)&xbeeRelay.counterX2out, sizeof(int)); if (!can.txWrite(msg)) data.canFault = true; - xbee.receive(msg); + xbeeRelay.send(msg); // Internal temperature sendCAN(SYS_TEMP_ID, data.internalTemp); @@ -152,14 +151,14 @@ memcpy(&msg.data[0], (void*)&data.dcdcFan1Duty, sizeof(float)); memcpy(&msg.data[4], (void*)&data.dcdcFan2Duty, sizeof(float)); if (!can.txWrite(msg)) data.canFault = true; - xbee.receive(msg); + xbeeRelay.send(msg); msg.id = SYS_PWM_PUMP_ID; msg.len = 2*sizeof(float); memcpy(&msg.data[0], (void*)&data.dcdcPump1Duty, sizeof(float)); memcpy(&msg.data[4], (void*)&data.dcdcPump2Duty, sizeof(float)); if (!can.txWrite(msg)) data.canFault = true; - xbee.receive(msg); + xbeeRelay.send(msg); // IMD sendCAN(SYS_IMD_STATUS_ID, data.imdStatus); @@ -172,6 +171,6 @@ // Shutdown Switches sendCAN(SYS_SWITCHES_ID, data.switchState); - Thread::wait(100); + Thread::wait(CAN_LOOP*1000); } } \ No newline at end of file
--- a/outDiagnostics/outDiagnostics.h Sun Nov 16 02:43:58 2014 +0000 +++ b/outDiagnostics/outDiagnostics.h Tue Jan 06 20:45:26 2015 +0000 @@ -2,7 +2,6 @@ #define _OUT_DIAGNOSTICS_H #include "IOobjects.h" -#include "rtos.h" namespace outDiagnostics {
--- a/runTime/runTime.cpp Sun Nov 16 02:43:58 2014 +0000 +++ b/runTime/runTime.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -2,9 +2,8 @@ const float INTERNAL_OVER_TEMP_THRES = 60; // Overtemp at 60C -void runTime::thread_gather_10Hz(void const* args) { +void runTime::thread_gather(void const* args) { while(1) { - wdt.kick(); // GLV battery coulomb counter data.glvCurrent = glvBat.current(); @@ -39,20 +38,12 @@ if (data.internalTemp > INTERNAL_OVER_TEMP_THRES) data.internalOverTemp = true; else data.internalOverTemp = false; - // Xbees -/* data.xbee1MessagesIn = xbee1.messagesProcessedIn(); - data.xbee2MessagesIn = xbee2.messagesProcessedIn(); - data.xbee1MessagesOut = xbee1.messagesProcessedOut(); - data.xbee2MessagesOut = xbee2.messagesProcessedOut(); -*/ + // Error frame data.errorFrame = data.canFault<<0 | data.watchdogReset<<1 | data.internalOverTemp<<2 | (data.IMDlatchError!=0)<<3 | (data.AMSlatchError!=0)<<4 | data.imdError<<5 | data.dcdcError<<6 | data.glvOverCurrent<<7; - Thread::wait(100); + Thread::wait(GATHER_LOOP*1000); } } -void runTime::thread_gather_100Hz(void const* args) { - while(1) { - glvBat.sample(); // Integrate next sample in GLV Battery coulomb counter - dcdc.sample(); // Handle dc-dc filter and errors - Thread::wait(10); - } +void runTime::thread_sample(void const* args) { + glvBat.sample(); // Integrate next sample in GLV Battery coulomb counter + dcdc.sample(); // Handle dc-dc filter and errors } \ No newline at end of file
--- a/runTime/runTime.h Sun Nov 16 02:43:58 2014 +0000 +++ b/runTime/runTime.h Tue Jan 06 20:45:26 2015 +0000 @@ -5,8 +5,8 @@ namespace runTime { - void thread_gather_10Hz(void const* args); - void thread_gather_100Hz(void const* args); + void thread_gather(void const* args); + void thread_sample(void const* args); } #endif \ No newline at end of file
--- a/serviceCAN/serviceCAN.cpp Sun Nov 16 02:43:58 2014 +0000 +++ b/serviceCAN/serviceCAN.cpp Tue Jan 06 20:45:26 2015 +0000 @@ -1,64 +1,80 @@ #include "serviceCAN.h" #include "CAN_RxIDs.h" - -bool canbus::serviceCAN() { +bool canbus::serviceCAN(CANMessage* fromXbee) +{ CANMessage msg; - if (can.rxRead(msg)) { - switch (msg.id) { - case FAN_CONTROL_ID: - if (msg.len != 2*sizeof(float)) break; - memcpy((void*)&CANdata.dcdcFan1Duty, &msg.data[0], sizeof(float)); - memcpy((void*)&CANdata.dcdcFan2Duty, &msg.data[4], sizeof(float)); - dcdc.setPwm(FAN1, CANdata.dcdcFan1Duty); - dcdc.setPwm(FAN2, CANdata.dcdcFan2Duty); - break; - - case PUMP_CONTROL_ID: - if (msg.len != 2*sizeof(float)) break; - memcpy((void*)&CANdata.dcdcPump1Duty, &msg.data[0], sizeof(float)); - memcpy((void*)&CANdata.dcdcPump2Duty, &msg.data[4], sizeof(float)); - dcdc.setPwm(PUMP1, CANdata.dcdcPump1Duty); - dcdc.setPwm(PUMP2, CANdata.dcdcPump2Duty); - break; - - case DCDC_CONTROL_ID: - if (msg.len != sizeof(char)) break; - if (msg.data[0] == 1) dcdc.set(1); - else dcdc.set(0); - break; - - case AMS_RELAYS_ID: - if (msg.len != sizeof(char)) break; - if ((msg.data[0] & 0xC0) == 0xC0) { - CANdata.airsClosed = true; - dcdc.set(1); - } else { - CANdata.airsClosed = false; - dcdc.set(0); - } - break; - - case GLVBAT_CLEARSOC_ID: - if (msg.len != sizeof(float)) break; - glvBat.resetToSOC(*((float*)(&msg.data[0]))); - break; - - case GLVBAT_CLEARAH_ID: - if (msg.len != sizeof(float)) break; - glvBat.resetToAh(*((float*)(&msg.data[0]))); - break; - - case GLVBAT_SETCAPAC_ID: - if (msg.len != sizeof(float)) break; - glvBat.changeCapacity(*((float*)(&msg.data[0]))); - break; - - default: - break; - } - xbee.receive(msg); + if (fromXbee != NULL) { + memcpy((void*)&msg, (void*)fromXbee, sizeof(CANMessage)); + } else { + if (!can.rxRead(msg)) return false; + } + + switch (msg.id) { + case FAN_CONTROL_ID: + if (msg.len != 2*sizeof(float)) break; + memcpy((void*)&CANdata.dcdcFan1Duty, &msg.data[0], sizeof(float)); + memcpy((void*)&CANdata.dcdcFan2Duty, &msg.data[4], sizeof(float)); + dcdc.setPwm(FAN1, CANdata.dcdcFan1Duty); + dcdc.setPwm(FAN2, CANdata.dcdcFan2Duty); + break; + + case PUMP_CONTROL_ID: + if (msg.len != 2*sizeof(float)) break; + memcpy((void*)&CANdata.dcdcPump1Duty, &msg.data[0], sizeof(float)); + memcpy((void*)&CANdata.dcdcPump2Duty, &msg.data[4], sizeof(float)); + dcdc.setPwm(PUMP1, CANdata.dcdcPump1Duty); + dcdc.setPwm(PUMP2, CANdata.dcdcPump2Duty); + break; + + case DCDC_CONTROL_ID: + if (msg.len != sizeof(char)) break; + if (msg.data[0] == 1) dcdc.set(1); + else dcdc.set(0); + break; + + case AMS_RELAYS_ID: + if (msg.len != sizeof(char)) break; + if ((msg.data[0] & (1<<3|1<<4|1<<5)) == (1<<3|1<<4|1<<5)) { // AIRs closed? 1<<3=posAIR, 1<<4=negAIR, 1<<5=tractiveEnable signal + CANdata.airsClosed = true; + dcdc.set(1); + } else { + CANdata.airsClosed = false; + dcdc.set(0); + } + break; + + case GLVBAT_CLEARSOC_ID: + if (msg.len != sizeof(float)) break; + glvBat.resetToSOC(*((float*)(&msg.data[0]))); + break; + + case GLVBAT_CLEARAH_ID: + if (msg.len != sizeof(float)) break; + glvBat.resetToAh(*((float*)(&msg.data[0]))); + break; + + case GLVBAT_SETCAPAC_ID: + if (msg.len != sizeof(float)) break; + glvBat.changeCapacity(*((float*)(&msg.data[0]))); + break; + case STEERING_RESET_ID: + NVIC_SystemReset(); + break; + default: + break; + } + + return true; + +} +// Check for incoming messages from the xbees +bool canbus::receiveMsgXbee() +{ + CANMessage msg; + if (xbeeRelay.receive(msg)) { // Incoming CAN message string received + if (!can.txWrite(msg)) data.canFault = true; // Send it out on the CAN bus + serviceCAN(&msg); // Send it into the local serviceCAN routine return true; - } - return false; + } else return false; } \ No newline at end of file
--- a/serviceCAN/serviceCAN.h Sun Nov 16 02:43:58 2014 +0000 +++ b/serviceCAN/serviceCAN.h Tue Jan 06 20:45:26 2015 +0000 @@ -1,13 +1,13 @@ #ifndef _SERVICE_CAN_H #define _SERVICE_CAN_H -#include "mbed.h" #include "IOobjects.h" const int DEVICE_CAN_TIMEOUT = 0.25; // Comms. lost to external device if a message is not received within 200 ms namespace canbus { - bool serviceCAN(); + bool serviceCAN(CANMessage* fromXbee=0); + bool receiveMsgXbee(); } #endif \ No newline at end of file