Chrono Tir
Revision 0:98f39b4055ea, committed 2020-02-03
- Comitter:
- pathae
- Date:
- Mon Feb 03 14:29:14 2020 +0000
- Commit message:
- chrono_tir_V2
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Mon Feb 03 14:29:14 2020 +0000
@@ -0,0 +1,130 @@
+/* A port test of the arduino voltmeter example using the
+4.3' PCT 4d systems touch screen display.
+
+uses the mbed_genie library ported from the arduino
+visie-genie library by Christian B
+
+The display serial TX and RX pins are connected to pin 9
+and pin 10 of the mbed
+
+The reset pin is not connected as reset function is not implemented
+
+Pin 15 of the mbed has a potentiometer wiper connected to it
+The other connections of the potentiometer are connected to +3.3V
+and 0V
+
+For setting up the display in Visie-Genie
+
+The display has an angular meter objecr, a LED digits object, two buttons
+and three static text objects.
+
+The program sends digital voltage readings to the LED digits and
+angular meter of the display module.
+
+The On and Off button has been set to report on change
+
+The baud rate of the display is set to 115200 baud
+
+*/
+
+#include "mbed.h"
+#include "mbed_genie.h"
+
+DigitalOut myled(LED1); //LED 1 for indication
+
+AnalogIn voltReading(PC_0); //Potentiometer wiper connected to pin 15
+
+int flag = 0; //holds the "power status" of the voltmeter. flag = 0 means voltmeter is "off", flag = 1 means the voltmeter is "on".
+float voltMeter; //holds the digital voltage value to be sent to the angular meter
+float voltLED; //holds the digital voltage value to be sent to the LED digits
+
+//Event handler for the 4d Systems display
+void myGenieEventHandler(void)
+{
+ genieFrame Event;
+ genieDequeueEvent(&Event);
+ //event report from an object
+ if(Event.reportObject.cmd == GENIE_REPORT_EVENT) {
+ /*
+ for example here we check if we received a message from 4dbuttons objects
+ the index is the button number, refer to the 4dgenie project to know the index
+ */
+ if (Event.reportObject.object == GENIE_OBJ_4DBUTTON) { // If the Reported Message was from a button
+ if (Event.reportObject.index == 0) {
+ //printf("Off Button pressed!\n\r");
+ wait(0.2);
+ flag=1;
+ }
+ if (Event.reportObject.index == 1) {
+ //printf("On Button pressed!\n\r");
+ wait(0.2);
+ flag=0;
+ }
+ }
+ }
+
+ //Cmd from a reported object (happens when an object read is requested)
+ // if(Event.reportObject.cmd == GENIE_REPORT_OBJ)
+ // {
+
+ // }
+
+}
+
+int main()
+
+{
+ SetupGenie();
+ genieAttachEventHandler(&myGenieEventHandler);
+ //genieResetDisplay();
+
+ printf("Langsters's mbed Visi-Genie Voltmeter demo \n\r");
+
+ //genieWriteContrast(15); //set screen contrast to full brightness
+
+ voltLED = 0.1;
+ while(1) {
+ printf("Test1\n\r");
+ //voltLED = 0;
+
+ if (flag == 1) {
+ //printf("Flag status: %d \r\n", flag);
+ /* wait (0.1);
+ voltLED = voltReading;
+ wait (0.1);
+ //printf("Volt bit Reading: %f \n\r",voltLED);
+ voltLED = voltLED * 3.3; //convert float reading to voltage
+ //printf("voltLED: %f\r\n",voltLED);
+
+ // voltLED = voltLED * 1000;
+ voltLED = 2.2;
+ printf("voltLED: %f\r\n",voltLED);
+ genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x00, voltLED); //write to Leddigits0 the value of voltLED
+ //wait (0.1);
+ wait (1);
+ voltMeter = voltLED/100;
+ genieWriteObject(GENIE_OBJ_ANGULAR_METER, 0x00, voltMeter); //write to Angularmeter0 the value of voltMeter*/
+ }
+
+ else if(flag == 0)
+
+ {
+ //printf("Flag status: %d \r\n", flag);
+ /* wait (0.1);
+ voltLED = 0;
+ genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x00, 0); //write to Leddigits0 the value of voltLED
+ wait (0.1);
+
+ //voltMeter = voltLED/100;
+ genieWriteObject(GENIE_OBJ_ANGULAR_METER, 0x00, 0); //write to Angularmeter0 the value of voltMeter
+ */
+ voltLED = voltLED + 0.1;;
+ printf("voltLED: %f\r\n",voltLED);
+ genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x00, voltLED*100);
+ wait (0.5);
+ genieWriteObject(GENIE_OBJ_ANGULAR_METER, 0x00, voltLED*20); //write to Angularmeter0 the value of voltMeter
+ }
+
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Feb 03 14:29:14 2020 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_genie.cpp Mon Feb 03 14:29:14 2020 +0000
@@ -0,0 +1,617 @@
+
+#include "mbed.h"
+#include "mbed_genie.h"
+
+DigitalOut genieReset(PC_7); //genie reset pin on pin 8 of the mbed
+
+Serial screen(PA_9,PA_10);
+Serial pc(USBTX,USBRX);
+Timer t;
+
+
+
+void _genieFlushEventQueue (void);
+void _handleError (void);
+void _geniePutchar (uint8_t c);
+uint8_t _genieGetchar (void);
+void _genieSetLinkState (uint16_t newstate);
+uint16_t _genieGetLinkState (void);
+bool _genieEnqueueEvent (uint8_t * data);
+//////////////////////////////////////////////////////////////
+// A structure to hold up to MAX_GENIE_EVENTS events receive
+// from the display
+//
+static genieEventQueueStruct _genieEventQueue;
+
+//////////////////////////////////////////////////////////////
+// Pointer to the user's event handler function
+//
+static genieUserEventHandlerPtr _genieUserHandler = NULL;
+
+
+//////////////////////////////////////////////////////////////
+// Simple 5-deep stack for the link state, this allows
+// genieDoEvents() to save the current state, receive a frame,
+// then restore the state
+//
+static uint8_t _genieLinkStates[5] = {GENIE_LINK_IDLE};
+//
+// Stack pointer
+//
+static uint8_t *_genieLinkState = &_genieLinkStates[0];
+
+
+//////////////////////////////////////////////////////////////
+// Number of mS the genieGetChar() function will wait before
+// giving up on the display
+static int _genieTimeout = TIMEOUT_PERIOD;
+
+
+//////////////////////////////////////////////////////////////
+// Number of times we have had a timeout
+static int _genieTimeouts = 0;
+
+
+//////////////////////////////////////////////////////////////
+// Global error variable
+static int _genieError = ERROR_NONE;
+
+
+
+
+static uint8_t rxframe_count = 0;
+
+
+//////////////////////////////////////////////////////////////
+// Number of fatal errors encountered
+static int _genieFatalErrors = 0;
+////////////////////// genieGetEventData ////////////////////////
+//
+// Returns the LSB and MSB of the event's data combined into
+// a single uint16
+//
+// The data is transmitted from the display in big-endian format
+// and stored the same so the user can't just access it as an int
+// directly from the structure.
+//
+uint16_t genieGetEventData (genieFrame * e) {
+ return (e->reportObject.data_msb << 8) + e->reportObject.data_lsb;
+}
+
+
+
+
+//////////////////////// genieEventIs ///////////////////////////
+//
+// Compares the cmd, object and index fields of the event's
+// structure.
+//
+// Returns: TRUE if all the fields match the caller's parms
+// FALSE if any of them don't
+//
+bool genieEventIs(genieFrame * e, uint8_t cmd, uint8_t object, uint8_t index) {
+
+
+ return (e->reportObject.cmd == cmd &&
+ e->reportObject.object == object &&
+ e->reportObject.index == index);
+
+
+}
+
+////////////////////// _geniePushLinkState //////////////////////
+//
+// Push a link state onto a FILO stack
+//
+void _geniePushLinkState (uint8_t newstate) {
+
+
+ _genieLinkState++;
+ _genieSetLinkState(newstate);
+
+
+}
+
+
+////////////////////// _geniePopLinkState //////////////////////
+//
+// Pop a link state from a FILO stack
+//
+void _geniePopLinkState (void) {
+ if (_genieLinkState > &_genieLinkStates[0]) {
+ *_genieLinkState = 0xFF;
+ _genieLinkState--;
+ }
+}
+
+///////////////// _genieFlushSerialInput ///////////////////
+//
+// Removes and discards all characters from the currently
+// used serial port's Rx buffer.
+//
+void _genieFlushSerialInput(void) {
+ do {
+ _genieGetchar();
+ } while (_genieError != ERROR_NOCHAR);
+}
+
+///////////////////////// _handleError /////////////////////////
+//
+// So far really just a debugging aid, but can be enhanced to
+// help recover from errors.
+//
+void _handleError (void) {
+// Serial2.write (_genieError + (1<<5));
+// if (_genieError == GENIE_NAK) genieResync();
+}
+
+
+
+
+////////////////////// _genieFlushEventQueue ////////////////////
+//
+// Reset all the event queue variables and start from scratch.
+//
+void _genieFlushEventQueue(void) {
+ _genieEventQueue.rd_index = 0;
+ _genieEventQueue.wr_index = 0;
+ _genieEventQueue.n_events = 0;
+}
+bool GenieReadable(void){
+ if (screen.readable())
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+///////////////////////// genieDoEvents /////////////////////////
+//
+// This is the heart of the Genie comms state machine.
+//
+uint16_t genieDoEvents (void) {
+ uint8_t c;
+ static uint8_t rx_data[6];
+ static uint8_t checksum = 0;
+
+ if (GenieReadable())
+ {
+ c = _genieGetchar();
+ //pc.putc(c);
+
+ ////////////////////////////////////////////
+ //
+ // If there are no characters to process and we have
+ // queued events call the user's handler function.
+ //
+ if (_genieError == ERROR_NOCHAR) {
+ //pc.printf("EventCalled!\n\r");
+ if (_genieEventQueue.n_events > 0 && _genieUserHandler!= NULL) (_genieUserHandler)();
+ return GENIE_EVENT_NONE;
+ }
+
+ ///////////////////////////////////////////
+ //
+ // Main state machine
+ //
+ switch (_genieGetLinkState()) {
+ case GENIE_LINK_IDLE:
+ switch (c) {
+ case GENIE_REPORT_EVENT:
+ // event frame out of the blue, set the link state
+ // and fall through to the frame-accumulate code
+ // at the end of this function
+ _geniePushLinkState(GENIE_LINK_RXEVENT);
+ break;
+
+ default:
+ // error, bad character, no other character
+ // is acceptable in this state
+ return GENIE_EVENT_RXCHAR;
+
+ }
+ break;
+
+ case GENIE_LINK_WFAN:
+ switch (c) {
+
+
+ case GENIE_ACK:
+ _geniePopLinkState();
+ return GENIE_EVENT_RXCHAR;
+
+
+ case GENIE_NAK:
+ _geniePopLinkState();
+ _genieError = ERROR_NAK;
+ _handleError();
+ return GENIE_EVENT_RXCHAR;
+
+ case GENIE_REPORT_EVENT:
+ // event frame out of the blue while waiting for an ACK
+ // save/set the link state and fall through to the
+ // frame-accumulate code at the end of this function
+ _geniePushLinkState(GENIE_LINK_RXEVENT);
+ break;
+
+
+ case GENIE_REPORT_OBJ:
+ default:
+ // error, bad character
+ return GENIE_EVENT_RXCHAR;
+ }
+ break;
+
+
+ case GENIE_LINK_WF_RXREPORT: // waiting for the first byte of a report
+ switch (c) {
+
+ case GENIE_REPORT_EVENT:
+ // event frame out of the blue while waiting for the first
+ // byte of a report frame
+ // save/set the link state and fall through to the
+ // frame-accumulate code at the end of this function
+ _geniePushLinkState(GENIE_LINK_RXEVENT);
+ break;
+
+
+ case GENIE_REPORT_OBJ:
+ // first byte of a report frame
+ // replace the GENIE_LINK_WF_RXREPORT link state
+ // with GENIE_LINK_RXREPORT to indicate that we
+ // are now receiving a report frame
+ _geniePopLinkState();
+ _geniePushLinkState(GENIE_LINK_RXREPORT);
+ break;
+
+
+ case GENIE_ACK:
+ case GENIE_NAK:
+ default:
+ // error, bad character
+ return GENIE_EVENT_RXCHAR;
+ // break;
+ }
+
+
+ case GENIE_LINK_RXREPORT: // already receiving report
+ case GENIE_LINK_RXEVENT: // already receiving event
+ default:
+ break;
+
+ }
+
+
+ ///////////////////////////////////////////////////////
+ // We get here if we are in the process of receiving
+ // a report or event frame. Accumulate GENIE_FRAME_SIZE
+ // bytes into a local buffer then queue them as a frame
+ // into the event queue
+ //
+ if (_genieGetLinkState() == GENIE_LINK_RXREPORT || \
+ _genieGetLinkState() == GENIE_LINK_RXEVENT) {
+
+ checksum = (rxframe_count == 0) ? c : checksum ^ c;
+
+
+ rx_data[rxframe_count] = c;
+
+
+ if (rxframe_count == GENIE_FRAME_SIZE -1) {
+ //pc.printf("FrameReceived!\n\r");
+ // all bytes received, if the CS is good
+ // queue the frame and restore the link state
+ if (checksum == 0) {
+ _genieEnqueueEvent(rx_data);
+ if (_genieEventQueue.n_events > 0 && _genieUserHandler!= NULL) (_genieUserHandler)();
+ //return GENIE_EVENT_NONE;
+ rxframe_count = 0;
+ // revert the link state to whatever it was before
+ // we started accumulating this frame
+ _geniePopLinkState();
+ return GENIE_EVENT_RXCHAR;
+ } else {
+ _genieError = ERROR_BAD_CS;
+ _handleError();
+ }
+ }
+ rxframe_count++;
+ return GENIE_EVENT_RXCHAR;
+ }
+ }
+}
+
+////////////////////// genieDequeueEvent ///////////////////
+//
+// Copy the bytes from a queued input event to a buffer supplied
+// by the caller.
+//
+// Parms: genieFrame * buff, a pointer to the user's buffer
+//
+// Returns: TRUE if there was an event to copy
+// FALSE if not
+//
+bool genieDequeueEvent(genieFrame * buff) {
+
+
+ if (_genieEventQueue.n_events > 0) {
+ memcpy (buff, &_genieEventQueue.frames[_genieEventQueue.rd_index],
+ GENIE_FRAME_SIZE);
+ _genieEventQueue.rd_index++;
+ _genieEventQueue.rd_index &= MAX_GENIE_EVENTS -1;
+ _genieEventQueue.n_events--;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+
+
+////////////////////// _genieWaitForIdle ////////////////////////
+//
+// Wait for the link to become idle or for the timeout period,
+// whichever comes first.
+//
+void _genieWaitForIdle (void) {
+ uint16_t do_event_result;
+ long timeout = t.read_ms() + _genieTimeout;
+
+ for ( ; t.read_ms() < timeout;) {
+
+
+ do_event_result = genieDoEvents();
+ // if there was a character received from the
+ // display restart the timeout because doEvents
+ // is in the process of receiving something
+ if (do_event_result == GENIE_EVENT_RXCHAR) {
+ timeout = t.read_ms() + _genieTimeout;
+ return;
+ }
+
+ if (_genieGetLinkState() == GENIE_LINK_IDLE) {
+ return;
+ }
+ }
+ _genieError = ERROR_TIMEOUT;
+ _handleError();
+ return;
+}
+
+///////////////////////// genieWriteObject //////////////////////
+//
+// Write data to an object on the display
+//
+uint16_t genieWriteObject (uint16_t object, uint16_t index, uint16_t data)
+{
+ uint16_t msb, lsb ;
+ uint8_t checksum ;
+
+
+ _genieWaitForIdle();
+
+
+ lsb = data&0xFF;
+ msb = (data>>8) & 0xFF;
+
+
+ _genieError = ERROR_NONE;
+
+
+ _geniePutchar(GENIE_WRITE_OBJ) ; checksum = GENIE_WRITE_OBJ ;
+ _geniePutchar(object) ; checksum ^= object ;
+ _geniePutchar(index) ; checksum ^= index ;
+ _geniePutchar(msb) ; checksum ^= msb;
+ _geniePutchar(lsb) ; checksum ^= lsb;
+ _geniePutchar(checksum) ;
+
+
+ _geniePushLinkState(GENIE_LINK_WFAN);
+}
+
+/////////////////////// genieWriteContrast //////////////////////
+//
+// Alter the display contrast (backlight)
+//
+// Parms: uint8_t value: The required contrast setting, only
+// values from 0 to 15 are valid. 0 or 1 for most displays
+// and 0 to 15 for the uLCD-43
+//
+void genieWriteContrast (uint16_t value) {
+ unsigned int checksum ;
+
+
+ _genieWaitForIdle();
+
+
+ _geniePutchar(GENIE_WRITE_CONTRAST) ; checksum = GENIE_WRITE_CONTRAST ;
+ _geniePutchar(value) ; checksum ^= value ;
+ _geniePutchar(checksum) ;
+
+
+ _geniePushLinkState(GENIE_LINK_WFAN);
+
+
+}
+
+
+//////////////////////// _genieWriteStrX ///////////////////////
+//
+// Non-user function used by genieWriteStr() and genieWriteStrU()
+//
+static int _genieWriteStrX (uint16_t code, uint16_t index, char *string)
+{
+ char *p ;
+ unsigned int checksum ;
+ int len = strlen (string) ;
+
+
+ if (len > 255)
+ return -1 ;
+
+
+ _genieWaitForIdle();
+
+
+ _geniePutchar(code) ; checksum = code ;
+ _geniePutchar(index) ; checksum ^= index ;
+ _geniePutchar((unsigned char)len) ; checksum ^= len ;
+ for (p = string ; *p ; ++p) {
+ _geniePutchar (*p) ;
+ checksum ^= *p ;
+ }
+ _geniePutchar(checksum) ;
+
+
+ _geniePushLinkState(GENIE_LINK_WFAN);
+
+
+ return 0 ;
+}
+/////////////////////// genieWriteStr ////////////////////////
+//
+// Write a string to the display (ASCII)
+//
+uint16_t genieWriteStr (uint16_t index, char *string) {
+
+ return _genieWriteStrX (GENIE_WRITE_STR, index, string);
+}
+
+
+/////////////////////// genieWriteStrU ////////////////////////
+//
+// Write a string to the display (Unicode)
+//
+uint16_t genieWriteStrU (uint16_t index, char *string) {
+
+
+ return _genieWriteStrX (GENIE_WRITE_STRU, index, string);
+
+
+}
+/////////////////// genieAttachEventHandler //////////////////////
+//
+// "Attaches" a pointer to the users event handler by writing
+// the pointer into the variable used by doEVents()
+//
+void genieAttachEventHandler (genieUserEventHandlerPtr handler) {
+ _genieUserHandler = handler;
+}
+
+
+////////////////////// _genieEnqueueEvent ///////////////////
+//
+// Copy the bytes from a buffer supplied by the caller
+// to the input queue
+//
+// Parms: uint8_t * data, a pointer to the user's data
+//
+// Returns: TRUE if there was an empty location in the queue
+// to copy the data into
+// FALSE if not
+// Sets: ERROR_REPLY_OVR if there was no room in the queue
+//
+bool _genieEnqueueEvent (uint8_t * data) {
+
+
+ if (_genieEventQueue.n_events < MAX_GENIE_EVENTS-2) {
+ memcpy (&_genieEventQueue.frames[_genieEventQueue.wr_index], data,
+ GENIE_FRAME_SIZE);
+ _genieEventQueue.wr_index++;
+ _genieEventQueue.wr_index &= MAX_GENIE_EVENTS -1;
+ _genieEventQueue.n_events++;
+ return TRUE;
+ } else {
+ _genieError = ERROR_REPLY_OVR;
+ _handleError();
+ return FALSE;
+ }
+}
+///////////////////// _genieSetLinkState ////////////////////////
+//
+// Set the logical state of the link to the display.
+//
+// Parms: uint16_t newstate, a value to be written to the
+// link's _genieLinkState variable. Valid values are
+// GENIE_LINK_IDLE 0
+// GENIE_LINK_WFAN 1 // waiting for Ack or Nak
+// GENIE_LINK_WF_RXREPORT 2 // waiting for a report frame
+// GENIE_LINK_RXREPORT 3 // receiving a report frame
+// GENIE_LINK_RXEVENT 4 // receiving an event frame
+// GENIE_LINK_SHDN 5
+//
+void _genieSetLinkState (uint16_t newstate) {
+
+ *_genieLinkState = newstate;
+
+
+ if (newstate == GENIE_LINK_RXREPORT || \
+ newstate == GENIE_LINK_RXEVENT)
+ rxframe_count = 0;
+}
+
+
+/////////////////////// _genieGetLinkState //////////////////////
+//
+// Get the current logical state of the link to the display.
+//
+uint16_t _genieGetLinkState (void) {
+ return *_genieLinkState;
+}
+
+/////////////////////// _geniePutchar ///////////////////////////
+//
+// Output the supplied character to the Genie display over
+// the selected serial port
+//
+void _geniePutchar (uint8_t c) {
+ // if (screen != NULL)
+ screen.putc(c);
+}
+
+
+//////////////////////// _genieGetchar //////////////////////////
+//
+// Get a character from the selected Genie serial port
+//
+// Returns: ERROR_NOHANDLER if an Rx handler has not
+// been defined
+// ERROR_NOCHAR if no bytes have beeb received
+// The char if there was one to get
+// Sets: _genieError with any errors encountered
+//
+uint8_t _genieGetchar() {
+ uint16_t result;
+
+
+ _genieError = ERROR_NONE;
+
+ return (screen.getc());
+}
+
+void RxIrqHandler(void)
+{
+ do
+ {
+ genieDoEvents();
+ }
+ while(screen.readable ());
+}
+
+
+void TickerIrq(void)
+{
+}
+
+
+void SetupGenie(void)
+{
+ screen.baud(115200);
+ pc.baud(115200);
+ screen.attach(&RxIrqHandler,Serial::RxIrq);
+ t.start();
+ // EventChk.attach(&TickerIrq,0.05);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_genie.h Mon Feb 03 14:29:14 2020 +0000
@@ -0,0 +1,136 @@
+#undef GENIE_DEBUG
+
+#define GENIE_VERSION "GenieMbed 17-Nov-2013"
+
+// Genie commands & replys:
+
+#define GENIE_ACK 0x06
+#define GENIE_NAK 0x15
+
+#define TIMEOUT_PERIOD 500
+#define RESYNC_PERIOD 100
+
+#define GENIE_READ_OBJ 0
+#define GENIE_WRITE_OBJ 1
+#define GENIE_WRITE_STR 2
+#define GENIE_WRITE_STRU 3
+#define GENIE_WRITE_CONTRAST 4
+#define GENIE_REPORT_OBJ 5
+#define GENIE_REPORT_EVENT 7
+
+// Objects
+// the manual says:
+// Note: Object IDs may change with future releases; it is not
+// advisable to code their values as constants.
+
+#define GENIE_OBJ_DIPSW 0
+#define GENIE_OBJ_KNOB 1
+#define GENIE_OBJ_ROCKERSW 2
+#define GENIE_OBJ_ROTARYSW 3
+#define GENIE_OBJ_SLIDER 4
+#define GENIE_OBJ_TRACKBAR 5
+#define GENIE_OBJ_WINBUTTON 6
+#define GENIE_OBJ_ANGULAR_METER 7
+#define GENIE_OBJ_COOL_GAUGE 8
+#define GENIE_OBJ_CUSTOM_DIGITS 9
+#define GENIE_OBJ_FORM 10
+#define GENIE_OBJ_GAUGE 11
+#define GENIE_OBJ_IMAGE 12
+#define GENIE_OBJ_KEYBOARD 13
+#define GENIE_OBJ_LED 14
+#define GENIE_OBJ_LED_DIGITS 15
+#define GENIE_OBJ_METER 16
+#define GENIE_OBJ_STRINGS 17
+#define GENIE_OBJ_THERMOMETER 18
+#define GENIE_OBJ_USER_LED 19
+#define GENIE_OBJ_VIDEO 20
+#define GENIE_OBJ_STATIC_TEXT 21
+#define GENIE_OBJ_SOUND 22
+#define GENIE_OBJ_TIMER 23
+#define GENIE_OBJ_SPECTRUM 24
+#define GENIE_OBJ_SCOPE 25
+#define GENIE_OBJ_TANK 26
+#define GENIE_OBJ_USERIMAGES 27
+#define GENIE_OBJ_PINOUTPUT 28
+#define GENIE_OBJ_PININPUT 29
+#define GENIE_OBJ_4DBUTTON 30
+#define GENIE_OBJ_ANIBUTTON 31
+#define GENIE_OBJ_COLORPICKER 32
+#define GENIE_OBJ_USERBUTTON 33
+
+// Structure to store replys returned from a display
+
+#define GENIE_FRAME_SIZE 6
+struct genieFrameReportObj {
+ uint8_t cmd;
+ uint8_t object;
+ uint8_t index;
+ uint8_t data_msb;
+ uint8_t data_lsb;
+};
+
+/////////////////////////////////////////////////////////////////////
+// The Genie frame definition
+//
+// The union allows the data to be referenced as an array of uint8_t
+// or a structure of type genieFrameReportObj, eg
+//
+// genieFrame f;
+// f.bytes[4];
+// f.reportObject.data_lsb
+//
+// both methods get the same byte
+//
+union genieFrame {
+ uint8_t bytes[GENIE_FRAME_SIZE];
+ genieFrameReportObj reportObject;
+};
+
+#define MAX_GENIE_EVENTS 16 // MUST be a power of 2
+#define MAX_GENIE_FATALS 10
+
+struct genieEventQueueStruct {
+ genieFrame frames[MAX_GENIE_EVENTS];
+ uint8_t rd_index;
+ uint8_t wr_index;
+ uint8_t n_events;
+};
+
+typedef void (*geniePutCharFuncPtr) (uint8_t c, uint32_t baud);
+typedef uint16_t (*genieGetCharFuncPtr) (void);
+typedef void (*genieUserEventHandlerPtr) (void);
+
+#define ERROR_NONE 0
+#define ERROR_TIMEOUT -1 // 255 0xFF
+#define ERROR_NOHANDLER -2 // 254 0xFE
+#define ERROR_NOCHAR -3 // 253 0xFD
+#define ERROR_NAK -4 // 252 0xFC
+#define ERROR_REPLY_OVR -5 // 251 0xFB
+#define ERROR_RESYNC -6 // 250 0xFA
+#define ERROR_NODISPLAY -7 // 249 0xF9
+#define ERROR_BAD_CS -8 // 248 0xF8
+
+#define GENIE_LINK_IDLE 0
+#define GENIE_LINK_WFAN 1 // waiting for Ack or Nak
+#define GENIE_LINK_WF_RXREPORT 2 // waiting for a report frame
+#define GENIE_LINK_RXREPORT 3 // receiving a report frame
+#define GENIE_LINK_RXEVENT 4 // receiving an event frame
+#define GENIE_LINK_SHDN 5
+
+#define GENIE_EVENT_NONE 0
+#define GENIE_EVENT_RXCHAR 1
+
+#ifndef TRUE
+#define TRUE (1==1)
+#define FALSE (!TRUE)
+#endif
+
+void SetupGenie(void);
+void genieAttachEventHandler (genieUserEventHandlerPtr handler);
+extern bool genieDequeueEvent (genieFrame * buff);
+extern bool genieEventIs (genieFrame * e, uint8_t cmd, uint8_t object, uint8_t index);
+extern uint16_t genieGetEventData (genieFrame * e);
+extern uint16_t genieWriteObject (uint16_t object, uint16_t index, uint16_t data);
+extern uint16_t genieWriteStr (uint16_t index, char *string);
+extern void genieWriteContrast (uint16_t value);
+