Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of 4dGENIE by
mbed_genie.cpp@5:3eb81723edc5, 2014-06-18 (annotated)
- 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?
User | Revision | Line number | New 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 | } |