Patrice HAESAERT
/
chrono_TIR_V1
Chrono TIR
Revision 0:f38ea4ed5621, committed 2020-01-22
- Comitter:
- pathae
- Date:
- Wed Jan 22 10:26:34 2020 +0000
- Commit message:
- chrono_TIR_V1
Changed in this revision
diff -r 000000000000 -r f38ea4ed5621 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Jan 22 10:26:34 2020 +0000 @@ -0,0 +1,85 @@ +/* 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 PA_9 +and pin PA_10 of the mbed + +The reset pin is not connected as reset function is not implemented + +For setting up the display in Visie-Genie + +The display has an gauge meter object, a LED digits object, two buttons +and three static text objects. + +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 + +int flag = 0; //holds the "power status" of the voltmeter. flag = 0 means voltmeter is "off", flag = 1 means the voltmeter is "on". +float chrono; //holds the digital voltage value to be sent to the angular meter + +//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); + genieWriteContrast(10); //set screen contrast to full brightness + chrono=99; + + while(1) { + + if (flag == 1) { + //printf("Flag status: %d \r\n", flag); + chrono=chrono-1; + genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x00, chrono); //write to Leddigits0 the value of voltLED + genieWriteObject(GENIE_OBJ_GAUGE , 0x00, chrono); //write to Angularmeter0 the value of voltMeter*/ + wait (0.5); + } + + else if(flag == 0){ + genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x00, 0); + genieWriteObject(GENIE_OBJ_GAUGE , 0x00, 0); //write to Angularmeter0 the value of voltMeter + chrono=99; + wait (0.5); + } + + } + +} \ No newline at end of file
diff -r 000000000000 -r f38ea4ed5621 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Jan 22 10:26:34 2020 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400 \ No newline at end of file
diff -r 000000000000 -r f38ea4ed5621 mbed_genie.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_genie.cpp Wed Jan 22 10:26:34 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(9600); + pc.baud(9600); + screen.attach(&RxIrqHandler,Serial::RxIrq); + t.start(); + // EventChk.attach(&TickerIrq,0.05); +}
diff -r 000000000000 -r f38ea4ed5621 mbed_genie.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_genie.h Wed Jan 22 10:26:34 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); +