Mbed 4dGenie class

Dependents:   Genie_Test 039847382-S3_DS1621_and_LCD_V1

This is a work in progress.

4dGenie class to use with 4dLCD screens that are using the genie environment.

There are still some rare occasions where the 4dLCD might crash, for now i have no solution to this except doing a reset of the 4dLCD.

Please make sure to have the most up to date PmmC loaded on the screen.

usage example :

Mbed4dGenie test program

#include "mbed.h"
#include "mbed_genie.h"

DigitalOut myled(LED1);
/*
    The Mbed4dGenie class requires 3 parameters
    1 - Tx pin
    2 - Rx pin
    3 - Reset pin
*/
Mbed4dGenie lcd4d(PTE0,PTE1,PTB9);



int main() {
    int temp = 0;
printf("Mbed Genie demo \n\r");
lcd4d.Start();


 /*
 for example, in this loop we increment the thermometer0 object from 0 to 100
 */
 
    while(1) {
        if(temp >= 100)
        {
            temp = -1;
        }
        else
        {
            temp++;
        }

        lcd4d.genieWriteObject(GENIE_OBJ_LED_DIGITS,1,temp);

        myled = 1;
        wait(0.05);
        myled = 0;
        wait(0.05);
    }
}
Committer:
chris215
Date:
Wed Jun 18 01:02:45 2014 +0000
Revision:
5:3eb81723edc5
Parent:
4:23c46eb6f0db
changed default speed to 115200 bauds

Who changed what in which revision?

UserRevisionLine numberNew contents of line
chris215 0:d2ed5a44c802 1
chris215 0:d2ed5a44c802 2 #include "mbed.h"
chris215 0:d2ed5a44c802 3 #include "mbed_genie.h"
chris215 0:d2ed5a44c802 4
chris215 0:d2ed5a44c802 5 Serial pc(USBTX,USBRX);
chris215 0:d2ed5a44c802 6
chris215 3:11c49c49cd1a 7 Mbed4dGenie::Mbed4dGenie(PinName TxPin,PinName RxPin, PinName resetpin) : _screen(TxPin,RxPin) , _reset(resetpin)
chris215 2:f283764fe9b7 8 {
chris215 3:11c49c49cd1a 9 //reset the 4d screen
chris215 5:3eb81723edc5 10 _screen.baud(115200);
chris215 4:23c46eb6f0db 11 _reset = 0;
chris215 3:11c49c49cd1a 12 wait(0.25);
chris215 4:23c46eb6f0db 13 _reset = 1;
chris215 2:f283764fe9b7 14 _genieLinkStates[4] = GENIE_LINK_IDLE;
chris215 2:f283764fe9b7 15 _genieLinkStates[3] = GENIE_LINK_IDLE;
chris215 2:f283764fe9b7 16 _genieLinkStates[2] = GENIE_LINK_IDLE;
chris215 2:f283764fe9b7 17 _genieLinkStates[1] = GENIE_LINK_IDLE;
chris215 2:f283764fe9b7 18 _genieLinkStates[0] = GENIE_LINK_IDLE;
chris215 2:f283764fe9b7 19 _genieLinkState = &_genieLinkStates[0];
chris215 2:f283764fe9b7 20
chris215 2:f283764fe9b7 21 _genieTimeout = TIMEOUT_PERIOD;
chris215 2:f283764fe9b7 22 _genieError = ERROR_NONE;
chris215 2:f283764fe9b7 23 rxframe_count = 0;
chris215 2:f283764fe9b7 24
chris215 2:f283764fe9b7 25 _genieUserHandler = NULL;
chris215 2:f283764fe9b7 26 _screen.attach(this,&Mbed4dGenie::RxIrqHandler,Serial::RxIrq);
chris215 2:f283764fe9b7 27 _t.start();
chris215 2:f283764fe9b7 28 }
chris215 2:f283764fe9b7 29 void Mbed4dGenie::genieAttachEventHandler(genieUserEventHandlerPtr handler)
chris215 2:f283764fe9b7 30 {
chris215 2:f283764fe9b7 31 _genieUserHandler = handler;
chris215 2:f283764fe9b7 32 }
chris215 2:f283764fe9b7 33 void Mbed4dGenie::RxIrqHandler(void)
chris215 2:f283764fe9b7 34 {
chris215 2:f283764fe9b7 35 do
chris215 2:f283764fe9b7 36 {
chris215 3:11c49c49cd1a 37 genieDoEvents();
chris215 2:f283764fe9b7 38 }
chris215 2:f283764fe9b7 39 while(_screen.readable ());
chris215 2:f283764fe9b7 40 }
chris215 2:f283764fe9b7 41 //////////////////////// _genieGetchar //////////////////////////
chris215 2:f283764fe9b7 42 //
chris215 2:f283764fe9b7 43 // Get a character from the selected Genie serial port
chris215 2:f283764fe9b7 44 //
chris215 2:f283764fe9b7 45 // Returns: ERROR_NOHANDLER if an Rx handler has not
chris215 2:f283764fe9b7 46 // been defined
chris215 2:f283764fe9b7 47 // ERROR_NOCHAR if no bytes have beeb received
chris215 2:f283764fe9b7 48 // The char if there was one to get
chris215 2:f283764fe9b7 49 // Sets: _genieError with any errors encountered
chris215 2:f283764fe9b7 50 //
chris215 2:f283764fe9b7 51 uint8_t Mbed4dGenie::_genieGetchar() {
chris215 2:f283764fe9b7 52
chris215 2:f283764fe9b7 53 _genieError = ERROR_NONE;
chris215 2:f283764fe9b7 54
chris215 2:f283764fe9b7 55 return (_screen.getc());
chris215 2:f283764fe9b7 56 }
chris215 2:f283764fe9b7 57 ///////////////////// _genieSetLinkState ////////////////////////
chris215 2:f283764fe9b7 58 //
chris215 2:f283764fe9b7 59 // Set the logical state of the link to the display.
chris215 2:f283764fe9b7 60 //
chris215 2:f283764fe9b7 61 // Parms: uint16_t newstate, a value to be written to the
chris215 2:f283764fe9b7 62 // link's _genieLinkState variable. Valid values are
chris215 2:f283764fe9b7 63 // GENIE_LINK_IDLE 0
chris215 2:f283764fe9b7 64 // GENIE_LINK_WFAN 1 // waiting for Ack or Nak
chris215 2:f283764fe9b7 65 // GENIE_LINK_WF_RXREPORT 2 // waiting for a report frame
chris215 2:f283764fe9b7 66 // GENIE_LINK_RXREPORT 3 // receiving a report frame
chris215 2:f283764fe9b7 67 // GENIE_LINK_RXEVENT 4 // receiving an event frame
chris215 2:f283764fe9b7 68 // GENIE_LINK_SHDN 5
chris215 2:f283764fe9b7 69 //
chris215 2:f283764fe9b7 70 void Mbed4dGenie::_genieSetLinkState (uint16_t newstate) {
chris215 2:f283764fe9b7 71
chris215 2:f283764fe9b7 72 *_genieLinkState = newstate;
chris215 0:d2ed5a44c802 73
chris215 0:d2ed5a44c802 74
chris215 2:f283764fe9b7 75 if (newstate == GENIE_LINK_RXREPORT || \
chris215 2:f283764fe9b7 76 newstate == GENIE_LINK_RXEVENT)
chris215 2:f283764fe9b7 77 rxframe_count = 0;
chris215 2:f283764fe9b7 78 }
chris215 2:f283764fe9b7 79
chris215 2:f283764fe9b7 80
chris215 2:f283764fe9b7 81 /////////////////////// _genieGetLinkState //////////////////////
chris215 2:f283764fe9b7 82 //
chris215 2:f283764fe9b7 83 // Get the current logical state of the link to the display.
chris215 2:f283764fe9b7 84 //
chris215 2:f283764fe9b7 85 uint16_t Mbed4dGenie::_genieGetLinkState (void) {
chris215 2:f283764fe9b7 86 return *_genieLinkState;
chris215 2:f283764fe9b7 87 }
chris215 2:f283764fe9b7 88
chris215 2:f283764fe9b7 89 /////////////////////// _geniePutchar ///////////////////////////
chris215 2:f283764fe9b7 90 //
chris215 2:f283764fe9b7 91 // Output the supplied character to the Genie display over
chris215 2:f283764fe9b7 92 // the selected serial port
chris215 2:f283764fe9b7 93 //
chris215 2:f283764fe9b7 94 void Mbed4dGenie::_geniePutchar (uint8_t c) {
chris215 2:f283764fe9b7 95 // if (screen != NULL)
chris215 2:f283764fe9b7 96 _screen.putc(c);
chris215 2:f283764fe9b7 97 }
chris215 2:f283764fe9b7 98 ////////////////////// _genieEnqueueEvent ///////////////////
chris215 2:f283764fe9b7 99 //
chris215 2:f283764fe9b7 100 // Copy the bytes from a buffer supplied by the caller
chris215 2:f283764fe9b7 101 // to the input queue
chris215 2:f283764fe9b7 102 //
chris215 2:f283764fe9b7 103 // Parms: uint8_t * data, a pointer to the user's data
chris215 0:d2ed5a44c802 104 //
chris215 2:f283764fe9b7 105 // Returns: TRUE if there was an empty location in the queue
chris215 2:f283764fe9b7 106 // to copy the data into
chris215 2:f283764fe9b7 107 // FALSE if not
chris215 2:f283764fe9b7 108 // Sets: ERROR_REPLY_OVR if there was no room in the queue
chris215 2:f283764fe9b7 109 //
chris215 2:f283764fe9b7 110 bool Mbed4dGenie::_genieEnqueueEvent (uint8_t * data) {
chris215 2:f283764fe9b7 111
chris215 0:d2ed5a44c802 112
chris215 2:f283764fe9b7 113 if (_genieEventQueue.n_events < MAX_GENIE_EVENTS-2) {
chris215 2:f283764fe9b7 114 memcpy (&_genieEventQueue.frames[_genieEventQueue.wr_index], data,
chris215 2:f283764fe9b7 115 GENIE_FRAME_SIZE);
chris215 2:f283764fe9b7 116 _genieEventQueue.wr_index++;
chris215 2:f283764fe9b7 117 _genieEventQueue.wr_index &= MAX_GENIE_EVENTS -1;
chris215 2:f283764fe9b7 118 _genieEventQueue.n_events++;
chris215 2:f283764fe9b7 119 return TRUE;
chris215 2:f283764fe9b7 120 } else {
chris215 2:f283764fe9b7 121 _genieError = ERROR_REPLY_OVR;
chris215 2:f283764fe9b7 122 _handleError();
chris215 2:f283764fe9b7 123 return FALSE;
chris215 2:f283764fe9b7 124 }
chris215 2:f283764fe9b7 125 }
chris215 2:f283764fe9b7 126 ////////////////////// genieDequeueEvent ///////////////////
chris215 0:d2ed5a44c802 127 //
chris215 2:f283764fe9b7 128 // Copy the bytes from a queued input event to a buffer supplied
chris215 2:f283764fe9b7 129 // by the caller.
chris215 2:f283764fe9b7 130 //
chris215 2:f283764fe9b7 131 // Parms: genieFrame * buff, a pointer to the user's buffer
chris215 2:f283764fe9b7 132 //
chris215 2:f283764fe9b7 133 // Returns: TRUE if there was an event to copy
chris215 2:f283764fe9b7 134 // FALSE if not
chris215 2:f283764fe9b7 135 //
chris215 2:f283764fe9b7 136 bool Mbed4dGenie::genieDequeueEvent(genieFrame * buff) {
chris215 0:d2ed5a44c802 137
chris215 0:d2ed5a44c802 138
chris215 2:f283764fe9b7 139 if (_genieEventQueue.n_events > 0) {
chris215 2:f283764fe9b7 140 memcpy (buff, &_genieEventQueue.frames[_genieEventQueue.rd_index],
chris215 2:f283764fe9b7 141 GENIE_FRAME_SIZE);
chris215 2:f283764fe9b7 142 _genieEventQueue.rd_index++;
chris215 2:f283764fe9b7 143 _genieEventQueue.rd_index &= MAX_GENIE_EVENTS -1;
chris215 2:f283764fe9b7 144 _genieEventQueue.n_events--;
chris215 2:f283764fe9b7 145 return TRUE;
chris215 2:f283764fe9b7 146 }
chris215 2:f283764fe9b7 147 return FALSE;
chris215 2:f283764fe9b7 148 }
chris215 2:f283764fe9b7 149 ////////////////////// _genieWaitForIdle ////////////////////////
chris215 2:f283764fe9b7 150 //
chris215 2:f283764fe9b7 151 // Wait for the link to become idle or for the timeout period,
chris215 2:f283764fe9b7 152 // whichever comes first.
chris215 0:d2ed5a44c802 153 //
chris215 2:f283764fe9b7 154 void Mbed4dGenie::_genieWaitForIdle (void) {
chris215 2:f283764fe9b7 155 uint16_t do_event_result;
chris215 2:f283764fe9b7 156 long timeout = _t.read_ms() + _genieTimeout;
chris215 2:f283764fe9b7 157
chris215 2:f283764fe9b7 158 for ( ; _t.read_ms() < timeout;) {
chris215 2:f283764fe9b7 159
chris215 2:f283764fe9b7 160
chris215 2:f283764fe9b7 161 do_event_result = genieDoEvents();
chris215 2:f283764fe9b7 162 // if there was a character received from the
chris215 2:f283764fe9b7 163 // display restart the timeout because doEvents
chris215 2:f283764fe9b7 164 // is in the process of receiving something
chris215 2:f283764fe9b7 165 if (do_event_result == GENIE_EVENT_RXCHAR) {
chris215 2:f283764fe9b7 166 timeout = _t.read_ms() + _genieTimeout;
chris215 2:f283764fe9b7 167 return;
chris215 2:f283764fe9b7 168 }
chris215 2:f283764fe9b7 169
chris215 2:f283764fe9b7 170 if (_genieGetLinkState() == GENIE_LINK_IDLE) {
chris215 2:f283764fe9b7 171 return;
chris215 2:f283764fe9b7 172 }
chris215 2:f283764fe9b7 173 }
chris215 2:f283764fe9b7 174 _genieError = ERROR_TIMEOUT;
chris215 2:f283764fe9b7 175 _handleError();
chris215 2:f283764fe9b7 176 return;
chris215 2:f283764fe9b7 177 }
chris215 2:f283764fe9b7 178 ///////////////////////// genieWriteObject //////////////////////
chris215 0:d2ed5a44c802 179 //
chris215 2:f283764fe9b7 180 // Write data to an object on the display
chris215 0:d2ed5a44c802 181 //
chris215 2:f283764fe9b7 182 uint16_t Mbed4dGenie::genieWriteObject (uint16_t object, uint16_t index, uint16_t data)
chris215 2:f283764fe9b7 183 {
chris215 2:f283764fe9b7 184 uint16_t msb, lsb ;
chris215 2:f283764fe9b7 185 uint8_t checksum ;
chris215 2:f283764fe9b7 186
chris215 2:f283764fe9b7 187
chris215 2:f283764fe9b7 188 _genieWaitForIdle();
chris215 2:f283764fe9b7 189
chris215 2:f283764fe9b7 190
chris215 2:f283764fe9b7 191 lsb = data&0xFF;
chris215 2:f283764fe9b7 192 msb = (data>>8) & 0xFF;
chris215 2:f283764fe9b7 193
chris215 2:f283764fe9b7 194
chris215 2:f283764fe9b7 195 _genieError = ERROR_NONE;
chris215 2:f283764fe9b7 196
chris215 2:f283764fe9b7 197
chris215 2:f283764fe9b7 198 _geniePutchar(GENIE_WRITE_OBJ) ; checksum = GENIE_WRITE_OBJ ;
chris215 2:f283764fe9b7 199 _geniePutchar(object) ; checksum ^= object ;
chris215 2:f283764fe9b7 200 _geniePutchar(index) ; checksum ^= index ;
chris215 2:f283764fe9b7 201 _geniePutchar(msb) ; checksum ^= msb;
chris215 2:f283764fe9b7 202 _geniePutchar(lsb) ; checksum ^= lsb;
chris215 2:f283764fe9b7 203 _geniePutchar(checksum) ;
chris215 0:d2ed5a44c802 204
chris215 0:d2ed5a44c802 205
chris215 2:f283764fe9b7 206 _geniePushLinkState(GENIE_LINK_WFAN);
chris215 2:f283764fe9b7 207 return GENIE_EVENT_NONE;
chris215 2:f283764fe9b7 208 }
chris215 2:f283764fe9b7 209 /////////////////////// genieWriteContrast //////////////////////
chris215 2:f283764fe9b7 210 //
chris215 2:f283764fe9b7 211 // Alter the display contrast (backlight)
chris215 2:f283764fe9b7 212 //
chris215 2:f283764fe9b7 213 // Parms: uint8_t value: The required contrast setting, only
chris215 2:f283764fe9b7 214 // values from 0 to 15 are valid. 0 or 1 for most displays
chris215 2:f283764fe9b7 215 // and 0 to 15 for the uLCD-43
chris215 2:f283764fe9b7 216 //
chris215 2:f283764fe9b7 217 void Mbed4dGenie::genieWriteContrast (uint16_t value) {
chris215 2:f283764fe9b7 218 unsigned int checksum ;
chris215 2:f283764fe9b7 219
chris215 2:f283764fe9b7 220
chris215 2:f283764fe9b7 221 _genieWaitForIdle();
chris215 0:d2ed5a44c802 222
chris215 0:d2ed5a44c802 223
chris215 2:f283764fe9b7 224 _geniePutchar(GENIE_WRITE_CONTRAST) ; checksum = GENIE_WRITE_CONTRAST ;
chris215 2:f283764fe9b7 225 _geniePutchar(value) ; checksum ^= value ;
chris215 2:f283764fe9b7 226 _geniePutchar(checksum) ;
chris215 2:f283764fe9b7 227
chris215 2:f283764fe9b7 228
chris215 2:f283764fe9b7 229 _geniePushLinkState(GENIE_LINK_WFAN);
chris215 2:f283764fe9b7 230
chris215 2:f283764fe9b7 231
chris215 2:f283764fe9b7 232 }
chris215 2:f283764fe9b7 233 //////////////////////// _genieWriteStrX ///////////////////////
chris215 2:f283764fe9b7 234 //
chris215 2:f283764fe9b7 235 // Non-user function used by genieWriteStr() and genieWriteStrU()
chris215 2:f283764fe9b7 236 //
chris215 2:f283764fe9b7 237 int Mbed4dGenie::_genieWriteStrX (uint16_t code, uint16_t index, char *string)
chris215 2:f283764fe9b7 238 {
chris215 2:f283764fe9b7 239 char *p ;
chris215 2:f283764fe9b7 240 unsigned int checksum ;
chris215 2:f283764fe9b7 241 int len = strlen (string) ;
chris215 0:d2ed5a44c802 242
chris215 0:d2ed5a44c802 243
chris215 2:f283764fe9b7 244 if (len > 255)
chris215 2:f283764fe9b7 245 return -1 ;
chris215 2:f283764fe9b7 246
chris215 2:f283764fe9b7 247
chris215 2:f283764fe9b7 248 _genieWaitForIdle();
chris215 2:f283764fe9b7 249
chris215 2:f283764fe9b7 250
chris215 2:f283764fe9b7 251 _geniePutchar(code) ; checksum = code ;
chris215 2:f283764fe9b7 252 _geniePutchar(index) ; checksum ^= index ;
chris215 2:f283764fe9b7 253 _geniePutchar((unsigned char)len) ; checksum ^= len ;
chris215 2:f283764fe9b7 254 for (p = string ; *p ; ++p) {
chris215 2:f283764fe9b7 255 _geniePutchar (*p) ;
chris215 2:f283764fe9b7 256 checksum ^= *p ;
chris215 2:f283764fe9b7 257 }
chris215 2:f283764fe9b7 258 _geniePutchar(checksum) ;
chris215 2:f283764fe9b7 259
chris215 2:f283764fe9b7 260
chris215 2:f283764fe9b7 261 _geniePushLinkState(GENIE_LINK_WFAN);
chris215 0:d2ed5a44c802 262
chris215 0:d2ed5a44c802 263
chris215 2:f283764fe9b7 264 return 0 ;
chris215 2:f283764fe9b7 265 }
chris215 2:f283764fe9b7 266 /////////////////////// genieWriteStr ////////////////////////
chris215 2:f283764fe9b7 267 //
chris215 2:f283764fe9b7 268 // Write a string to the display (ASCII)
chris215 2:f283764fe9b7 269 //
chris215 2:f283764fe9b7 270 uint16_t Mbed4dGenie::genieWriteStr (uint16_t index, char *string) {
chris215 2:f283764fe9b7 271
chris215 2:f283764fe9b7 272 return _genieWriteStrX (GENIE_WRITE_STR, index, string);
chris215 2:f283764fe9b7 273 }
chris215 2:f283764fe9b7 274 /////////////////////// genieWriteStrU ////////////////////////
chris215 2:f283764fe9b7 275 //
chris215 2:f283764fe9b7 276 // Write a string to the display (Unicode)
chris215 2:f283764fe9b7 277 //
chris215 2:f283764fe9b7 278 uint16_t Mbed4dGenie::genieWriteStrU (uint16_t index, char *string) {
chris215 0:d2ed5a44c802 279
chris215 2:f283764fe9b7 280 return _genieWriteStrX (GENIE_WRITE_STRU, index, string);
chris215 0:d2ed5a44c802 281
chris215 2:f283764fe9b7 282 }
chris215 0:d2ed5a44c802 283 //////////////////////////////////////////////////////////////
chris215 0:d2ed5a44c802 284 // Number of fatal errors encountered
chris215 1:95e0e194a412 285 //static int _genieFatalErrors = 0;
chris215 0:d2ed5a44c802 286 ////////////////////// genieGetEventData ////////////////////////
chris215 0:d2ed5a44c802 287 //
chris215 0:d2ed5a44c802 288 // Returns the LSB and MSB of the event's data combined into
chris215 0:d2ed5a44c802 289 // a single uint16
chris215 0:d2ed5a44c802 290 //
chris215 0:d2ed5a44c802 291 // The data is transmitted from the display in big-endian format
chris215 0:d2ed5a44c802 292 // and stored the same so the user can't just access it as an int
chris215 0:d2ed5a44c802 293 // directly from the structure.
chris215 0:d2ed5a44c802 294 //
chris215 2:f283764fe9b7 295 uint16_t Mbed4dGenie::genieGetEventData (genieFrame * e) {
chris215 0:d2ed5a44c802 296 return (e->reportObject.data_msb << 8) + e->reportObject.data_lsb;
chris215 0:d2ed5a44c802 297 }
chris215 0:d2ed5a44c802 298
chris215 0:d2ed5a44c802 299
chris215 0:d2ed5a44c802 300
chris215 0:d2ed5a44c802 301
chris215 0:d2ed5a44c802 302 //////////////////////// genieEventIs ///////////////////////////
chris215 0:d2ed5a44c802 303 //
chris215 0:d2ed5a44c802 304 // Compares the cmd, object and index fields of the event's
chris215 0:d2ed5a44c802 305 // structure.
chris215 0:d2ed5a44c802 306 //
chris215 0:d2ed5a44c802 307 // Returns: TRUE if all the fields match the caller's parms
chris215 0:d2ed5a44c802 308 // FALSE if any of them don't
chris215 0:d2ed5a44c802 309 //
chris215 2:f283764fe9b7 310 bool Mbed4dGenie::genieEventIs(genieFrame * e, uint8_t cmd, uint8_t object, uint8_t index) {
chris215 0:d2ed5a44c802 311
chris215 0:d2ed5a44c802 312
chris215 0:d2ed5a44c802 313 return (e->reportObject.cmd == cmd &&
chris215 0:d2ed5a44c802 314 e->reportObject.object == object &&
chris215 0:d2ed5a44c802 315 e->reportObject.index == index);
chris215 0:d2ed5a44c802 316
chris215 0:d2ed5a44c802 317
chris215 0:d2ed5a44c802 318 }
chris215 0:d2ed5a44c802 319
chris215 0:d2ed5a44c802 320 ////////////////////// _geniePushLinkState //////////////////////
chris215 0:d2ed5a44c802 321 //
chris215 0:d2ed5a44c802 322 // Push a link state onto a FILO stack
chris215 0:d2ed5a44c802 323 //
chris215 2:f283764fe9b7 324 void Mbed4dGenie::_geniePushLinkState (uint8_t newstate) {
chris215 0:d2ed5a44c802 325
chris215 0:d2ed5a44c802 326
chris215 0:d2ed5a44c802 327 _genieLinkState++;
chris215 0:d2ed5a44c802 328 _genieSetLinkState(newstate);
chris215 0:d2ed5a44c802 329
chris215 0:d2ed5a44c802 330
chris215 0:d2ed5a44c802 331 }
chris215 0:d2ed5a44c802 332
chris215 0:d2ed5a44c802 333
chris215 0:d2ed5a44c802 334 ////////////////////// _geniePopLinkState //////////////////////
chris215 0:d2ed5a44c802 335 //
chris215 0:d2ed5a44c802 336 // Pop a link state from a FILO stack
chris215 0:d2ed5a44c802 337 //
chris215 2:f283764fe9b7 338 void Mbed4dGenie::_geniePopLinkState (void) {
chris215 0:d2ed5a44c802 339 if (_genieLinkState > &_genieLinkStates[0]) {
chris215 0:d2ed5a44c802 340 *_genieLinkState = 0xFF;
chris215 0:d2ed5a44c802 341 _genieLinkState--;
chris215 0:d2ed5a44c802 342 }
chris215 0:d2ed5a44c802 343 }
chris215 0:d2ed5a44c802 344
chris215 0:d2ed5a44c802 345 ///////////////// _genieFlushSerialInput ///////////////////
chris215 0:d2ed5a44c802 346 //
chris215 0:d2ed5a44c802 347 // Removes and discards all characters from the currently
chris215 0:d2ed5a44c802 348 // used serial port's Rx buffer.
chris215 0:d2ed5a44c802 349 //
chris215 2:f283764fe9b7 350 void Mbed4dGenie::_genieFlushSerialInput(void) {
chris215 0:d2ed5a44c802 351 do {
chris215 0:d2ed5a44c802 352 _genieGetchar();
chris215 0:d2ed5a44c802 353 } while (_genieError != ERROR_NOCHAR);
chris215 0:d2ed5a44c802 354 }
chris215 0:d2ed5a44c802 355
chris215 0:d2ed5a44c802 356 ///////////////////////// _handleError /////////////////////////
chris215 0:d2ed5a44c802 357 //
chris215 0:d2ed5a44c802 358 // So far really just a debugging aid, but can be enhanced to
chris215 0:d2ed5a44c802 359 // help recover from errors.
chris215 0:d2ed5a44c802 360 //
chris215 2:f283764fe9b7 361 void Mbed4dGenie::_handleError (void) {
chris215 5:3eb81723edc5 362 _genieError = ERROR_NONE;
chris215 5:3eb81723edc5 363
chris215 0:d2ed5a44c802 364 }
chris215 0:d2ed5a44c802 365
chris215 0:d2ed5a44c802 366
chris215 0:d2ed5a44c802 367
chris215 0:d2ed5a44c802 368
chris215 0:d2ed5a44c802 369 ////////////////////// _genieFlushEventQueue ////////////////////
chris215 0:d2ed5a44c802 370 //
chris215 0:d2ed5a44c802 371 // Reset all the event queue variables and start from scratch.
chris215 0:d2ed5a44c802 372 //
chris215 2:f283764fe9b7 373 void Mbed4dGenie::_genieFlushEventQueue(void) {
chris215 0:d2ed5a44c802 374 _genieEventQueue.rd_index = 0;
chris215 0:d2ed5a44c802 375 _genieEventQueue.wr_index = 0;
chris215 0:d2ed5a44c802 376 _genieEventQueue.n_events = 0;
chris215 0:d2ed5a44c802 377 }
chris215 2:f283764fe9b7 378 bool Mbed4dGenie::GenieReadable(void){
chris215 2:f283764fe9b7 379 if (_screen.readable())
chris215 0:d2ed5a44c802 380 {
chris215 0:d2ed5a44c802 381 return TRUE;
chris215 0:d2ed5a44c802 382 }
chris215 0:d2ed5a44c802 383 else
chris215 0:d2ed5a44c802 384 {
chris215 0:d2ed5a44c802 385 return FALSE;
chris215 0:d2ed5a44c802 386 }
chris215 0:d2ed5a44c802 387 }
chris215 0:d2ed5a44c802 388 ///////////////////////// genieDoEvents /////////////////////////
chris215 0:d2ed5a44c802 389 //
chris215 0:d2ed5a44c802 390 // This is the heart of the Genie comms state machine.
chris215 0:d2ed5a44c802 391 //
chris215 2:f283764fe9b7 392 uint16_t Mbed4dGenie::genieDoEvents (void) {
chris215 0:d2ed5a44c802 393 uint8_t c;
chris215 0:d2ed5a44c802 394 static uint8_t rx_data[6];
chris215 0:d2ed5a44c802 395 static uint8_t checksum = 0;
chris215 0:d2ed5a44c802 396
chris215 0:d2ed5a44c802 397 if (GenieReadable())
chris215 0:d2ed5a44c802 398 {
chris215 0:d2ed5a44c802 399 c = _genieGetchar();
chris215 0:d2ed5a44c802 400 //pc.putc(c);
chris215 0:d2ed5a44c802 401
chris215 0:d2ed5a44c802 402 ////////////////////////////////////////////
chris215 0:d2ed5a44c802 403 //
chris215 0:d2ed5a44c802 404 // If there are no characters to process and we have
chris215 0:d2ed5a44c802 405 // queued events call the user's handler function.
chris215 0:d2ed5a44c802 406 //
chris215 0:d2ed5a44c802 407 if (_genieError == ERROR_NOCHAR) {
chris215 0:d2ed5a44c802 408 //pc.printf("EventCalled!\n\r");
chris215 0:d2ed5a44c802 409 if (_genieEventQueue.n_events > 0 && _genieUserHandler!= NULL) (_genieUserHandler)();
chris215 0:d2ed5a44c802 410 return GENIE_EVENT_NONE;
chris215 0:d2ed5a44c802 411 }
chris215 0:d2ed5a44c802 412
chris215 0:d2ed5a44c802 413 ///////////////////////////////////////////
chris215 0:d2ed5a44c802 414 //
chris215 0:d2ed5a44c802 415 // Main state machine
chris215 0:d2ed5a44c802 416 //
chris215 0:d2ed5a44c802 417 switch (_genieGetLinkState()) {
chris215 0:d2ed5a44c802 418 case GENIE_LINK_IDLE:
chris215 0:d2ed5a44c802 419 switch (c) {
chris215 0:d2ed5a44c802 420 case GENIE_REPORT_EVENT:
chris215 0:d2ed5a44c802 421 // event frame out of the blue, set the link state
chris215 0:d2ed5a44c802 422 // and fall through to the frame-accumulate code
chris215 0:d2ed5a44c802 423 // at the end of this function
chris215 0:d2ed5a44c802 424 _geniePushLinkState(GENIE_LINK_RXEVENT);
chris215 0:d2ed5a44c802 425 break;
chris215 0:d2ed5a44c802 426
chris215 0:d2ed5a44c802 427 default:
chris215 0:d2ed5a44c802 428 // error, bad character, no other character
chris215 0:d2ed5a44c802 429 // is acceptable in this state
chris215 5:3eb81723edc5 430 pc.printf("error1\n\r");
chris215 0:d2ed5a44c802 431 return GENIE_EVENT_RXCHAR;
chris215 0:d2ed5a44c802 432
chris215 0:d2ed5a44c802 433 }
chris215 0:d2ed5a44c802 434 break;
chris215 0:d2ed5a44c802 435
chris215 0:d2ed5a44c802 436 case GENIE_LINK_WFAN:
chris215 0:d2ed5a44c802 437 switch (c) {
chris215 0:d2ed5a44c802 438
chris215 0:d2ed5a44c802 439
chris215 0:d2ed5a44c802 440 case GENIE_ACK:
chris215 0:d2ed5a44c802 441 _geniePopLinkState();
chris215 0:d2ed5a44c802 442 return GENIE_EVENT_RXCHAR;
chris215 0:d2ed5a44c802 443
chris215 0:d2ed5a44c802 444
chris215 0:d2ed5a44c802 445 case GENIE_NAK:
chris215 0:d2ed5a44c802 446 _geniePopLinkState();
chris215 0:d2ed5a44c802 447 _genieError = ERROR_NAK;
chris215 0:d2ed5a44c802 448 _handleError();
chris215 5:3eb81723edc5 449 pc.printf("error2:NAK\n\r");
chris215 0:d2ed5a44c802 450 return GENIE_EVENT_RXCHAR;
chris215 0:d2ed5a44c802 451
chris215 0:d2ed5a44c802 452 case GENIE_REPORT_EVENT:
chris215 0:d2ed5a44c802 453 // event frame out of the blue while waiting for an ACK
chris215 0:d2ed5a44c802 454 // save/set the link state and fall through to the
chris215 0:d2ed5a44c802 455 // frame-accumulate code at the end of this function
chris215 0:d2ed5a44c802 456 _geniePushLinkState(GENIE_LINK_RXEVENT);
chris215 0:d2ed5a44c802 457 break;
chris215 0:d2ed5a44c802 458
chris215 0:d2ed5a44c802 459
chris215 0:d2ed5a44c802 460 case GENIE_REPORT_OBJ:
chris215 0:d2ed5a44c802 461 default:
chris215 0:d2ed5a44c802 462 // error, bad character
chris215 0:d2ed5a44c802 463 return GENIE_EVENT_RXCHAR;
chris215 0:d2ed5a44c802 464 }
chris215 0:d2ed5a44c802 465 break;
chris215 0:d2ed5a44c802 466
chris215 0:d2ed5a44c802 467
chris215 0:d2ed5a44c802 468 case GENIE_LINK_WF_RXREPORT: // waiting for the first byte of a report
chris215 0:d2ed5a44c802 469 switch (c) {
chris215 0:d2ed5a44c802 470
chris215 0:d2ed5a44c802 471 case GENIE_REPORT_EVENT:
chris215 0:d2ed5a44c802 472 // event frame out of the blue while waiting for the first
chris215 0:d2ed5a44c802 473 // byte of a report frame
chris215 0:d2ed5a44c802 474 // save/set the link state and fall through to the
chris215 0:d2ed5a44c802 475 // frame-accumulate code at the end of this function
chris215 0:d2ed5a44c802 476 _geniePushLinkState(GENIE_LINK_RXEVENT);
chris215 0:d2ed5a44c802 477 break;
chris215 0:d2ed5a44c802 478
chris215 0:d2ed5a44c802 479
chris215 0:d2ed5a44c802 480 case GENIE_REPORT_OBJ:
chris215 0:d2ed5a44c802 481 // first byte of a report frame
chris215 0:d2ed5a44c802 482 // replace the GENIE_LINK_WF_RXREPORT link state
chris215 0:d2ed5a44c802 483 // with GENIE_LINK_RXREPORT to indicate that we
chris215 0:d2ed5a44c802 484 // are now receiving a report frame
chris215 0:d2ed5a44c802 485 _geniePopLinkState();
chris215 0:d2ed5a44c802 486 _geniePushLinkState(GENIE_LINK_RXREPORT);
chris215 0:d2ed5a44c802 487 break;
chris215 0:d2ed5a44c802 488
chris215 0:d2ed5a44c802 489
chris215 0:d2ed5a44c802 490 case GENIE_ACK:
chris215 0:d2ed5a44c802 491 case GENIE_NAK:
chris215 0:d2ed5a44c802 492 default:
chris215 0:d2ed5a44c802 493 // error, bad character
chris215 5:3eb81723edc5 494 pc.printf("error3\n\r");
chris215 0:d2ed5a44c802 495 return GENIE_EVENT_RXCHAR;
chris215 0:d2ed5a44c802 496 // break;
chris215 0:d2ed5a44c802 497 }
chris215 0:d2ed5a44c802 498
chris215 0:d2ed5a44c802 499
chris215 0:d2ed5a44c802 500 case GENIE_LINK_RXREPORT: // already receiving report
chris215 0:d2ed5a44c802 501 case GENIE_LINK_RXEVENT: // already receiving event
chris215 0:d2ed5a44c802 502 default:
chris215 0:d2ed5a44c802 503 break;
chris215 0:d2ed5a44c802 504
chris215 0:d2ed5a44c802 505 }
chris215 0:d2ed5a44c802 506
chris215 0:d2ed5a44c802 507
chris215 0:d2ed5a44c802 508 ///////////////////////////////////////////////////////
chris215 0:d2ed5a44c802 509 // We get here if we are in the process of receiving
chris215 0:d2ed5a44c802 510 // a report or event frame. Accumulate GENIE_FRAME_SIZE
chris215 0:d2ed5a44c802 511 // bytes into a local buffer then queue them as a frame
chris215 0:d2ed5a44c802 512 // into the event queue
chris215 0:d2ed5a44c802 513 //
chris215 0:d2ed5a44c802 514 if (_genieGetLinkState() == GENIE_LINK_RXREPORT || \
chris215 0:d2ed5a44c802 515 _genieGetLinkState() == GENIE_LINK_RXEVENT) {
chris215 0:d2ed5a44c802 516
chris215 0:d2ed5a44c802 517 checksum = (rxframe_count == 0) ? c : checksum ^ c;
chris215 0:d2ed5a44c802 518
chris215 0:d2ed5a44c802 519
chris215 0:d2ed5a44c802 520 rx_data[rxframe_count] = c;
chris215 0:d2ed5a44c802 521
chris215 0:d2ed5a44c802 522
chris215 0:d2ed5a44c802 523 if (rxframe_count == GENIE_FRAME_SIZE -1) {
chris215 0:d2ed5a44c802 524 //pc.printf("FrameReceived!\n\r");
chris215 0:d2ed5a44c802 525 // all bytes received, if the CS is good
chris215 0:d2ed5a44c802 526 // queue the frame and restore the link state
chris215 0:d2ed5a44c802 527 if (checksum == 0) {
chris215 0:d2ed5a44c802 528 _genieEnqueueEvent(rx_data);
chris215 0:d2ed5a44c802 529 if (_genieEventQueue.n_events > 0 && _genieUserHandler!= NULL) (_genieUserHandler)();
chris215 0:d2ed5a44c802 530 //return GENIE_EVENT_NONE;
chris215 0:d2ed5a44c802 531 rxframe_count = 0;
chris215 0:d2ed5a44c802 532 // revert the link state to whatever it was before
chris215 0:d2ed5a44c802 533 // we started accumulating this frame
chris215 0:d2ed5a44c802 534 _geniePopLinkState();
chris215 0:d2ed5a44c802 535 return GENIE_EVENT_RXCHAR;
chris215 0:d2ed5a44c802 536 } else {
chris215 0:d2ed5a44c802 537 _genieError = ERROR_BAD_CS;
chris215 0:d2ed5a44c802 538 _handleError();
chris215 5:3eb81723edc5 539 pc.printf("error4\n\r");
chris215 0:d2ed5a44c802 540 }
chris215 0:d2ed5a44c802 541 }
chris215 0:d2ed5a44c802 542 rxframe_count++;
chris215 0:d2ed5a44c802 543 return GENIE_EVENT_RXCHAR;
chris215 0:d2ed5a44c802 544 }
chris215 1:95e0e194a412 545 }
chris215 1:95e0e194a412 546 return GENIE_EVENT_NONE;
chris215 2:f283764fe9b7 547 }