Chrono Tir

Dependencies:   mbed

Committer:
pathae
Date:
Mon Feb 03 14:29:14 2020 +0000
Revision:
0:98f39b4055ea
chrono_tir_V2

Who changed what in which revision?

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