chrono

Dependencies:   mbed

Committer:
pathae
Date:
Mon Feb 03 14:36:55 2020 +0000
Revision:
1:79f936cc69dd
Parent:
0:f38ea4ed5621
Chrono

Who changed what in which revision?

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