//Radio serial interface uses ODD parity
//Appears widgets must be listed in order as they appear on the screen from top to bottom
//characters printed individually for detailed placement control, soft menu text must be separated into groups
#include <ezLCDLib.h>
#define LED_PIN 13
ezLCD3 lcd;
int option = 1; // 1=draw, 2=disabled, 3=toggle pressed, 4=toggle not pressed,
// 5=toggle pressed disabled, 6=toggle not pressed disabled.
int touch=0;
char rxdata[30];
uint8_t opCode;
uint8_t subopCode;
uint8_t packetBegin;
uint8_t packetLength;
uint8_t appendedLength;
uint8_t specialReports[9] = {
0x24,0x04,0x18,0x29,0x00,0x01,0x2E,0x98,0x03}; // enable serial data reporting
uint8_t acknowledge[6] = { // ack requred to get next packet from radio
0x24,0x01,0x10,0xF3,0x28,0x03};
uint8_t tuneUp[10] = {
0x24,0x05,0x18,0x36,0xFE,0x7B,0xEF,0x01,0xE0,0x03, };
uint8_t tuneDown[10] = {
0x24,0x05,0x18,0x36,0xDF,0x7B,0xEF,0x01,0xC1,0x03} ; // down button command
uint8_t buttonRelease[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0xEF,0x01,0xE1,0x03} ; // button release command
uint8_t button1[10] = {
0x24,0x05,0x18,0x36,0xFF,0x79,0xEF,0x01,0xDF,0x03} ; // keypad button 1
uint8_t button2[10] = {
0x24,0x05,0x18,0x36,0xFF,0x3B,0xEF,0x01,0xA1,0x03} ; // keypad button 2
uint8_t button3[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0xE7,0x01,0xD9,0x03} ; // keypad button 3
uint8_t button4[10] = {
0x24,0x05,0x18,0x36,0xFF,0x5B,0xEF,0x01,0xC1,0x03} ; // keypad button 4
uint8_t button5[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0xEB,0x01,0xDD,0x03} ; // keypad button 5
uint8_t button6[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0x6F,0x01,0x61,0x03} ; // keypad button 6
uint8_t button7[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0xAF,0x01,0xA1,0x03} ; // keypad button 7
uint8_t button8[10] = {
0x24,0x05,0x18,0x36,0xF7,0x7B,0xEF,0x01,0xD9,0x03} ; // keypad button 8
uint8_t button9[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7A,0xEF,0x01,0xE0,0x03} ; // keypad button 9
uint8_t button0[10] = {
0x24,0x05,0x18,0x36,0x7F,0x7B,0xEF,0x01,0x61,0x03} ; // keypad button 0
uint8_t buttonAsterisk[10] = {
0x24,0x05,0x18,0x36,0xFB,0x7B,0xEF,0x01,0xDD,0x03} ; // keypad button *
uint8_t buttonPound[10] = {
0x24,0x05,0x18,0x36,0xFF,0x6B,0xEF,0x01,0xD1,0x03} ; // keypad button #
uint8_t buttonMENU[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0xEF,0x00,0xE0,0x03} ; // keypad button MENU
uint8_t buttonPesc[10] = {
0x24,0x05,0x18,0x36,0xEF,0x7B,0xEF,0x01,0xD1,0x03} ; // keypad button Pesc
byte buttonEnter[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0xED,0x01,0xDF,0x03} ; // keypad button Enter
byte moreKey[10] = {
0x24,0x05,0x18,0x36,0xFD,0x7B,0xEF,0x01,0xDF,0x03} ; // more key
byte f1Key[10] = {
0x24,0x05,0x18,0x36,0xBF,0x7B,0xEF,0x01,0xA1,0x03} ; // soft key F1
byte f2Key[10] = {
0x24,0x05,0x18,0x36,0xFF,0x73,0xEF,0x01,0xD9,0x03} ; // soft key F2
byte fThreeKey[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0xEE,0x01,0xE0,0x03} ; //soft key F3
byte fFourKey[10] = {
0x24,0x05,0x18,0x36,0xFF,0x7B,0xCF,0x01,0xc1,0x03} ; // soft key F4
void setup()
{
Serial2.begin(9600, SERIAL_8O1);
lcd.begin( EZM_BAUD_RATE );
lcd.cls( BLACK, WHITE );
lcd.fontw(1, "sans24");
lcd.theme( 1, 1, 48, 0, 23, 3, 2, 1, 5, 1, 1); //small button theme ( 1, 1, 48, 0, 23, 3, 2, 1, 5, 1, 1 );
lcd.theme( 2, 1, 48, 0, 23, 3, 1, 105, 5, 1, 1 ); //tune buttons theme
lcd.fontw(1,"1");
lcd.theme( 3, 1, 48, 0, 23, 3, 2, 1, 5, 1, 1 ); //ENT button theme
//lcd.button( 18, 5, 110, 70, 30, 1, 0, 3, 1, 1 ); // just test buttons before I knew about shadowing
// lcd.button( 19, 85, 110, 70, 30, 1, 0, 3, 1, 1 );
//lcd.button( 20, 165, 110, 70, 30, 1, 0, 3, 1, 1);
// lcd.button( 21, 245, 110, 70, 30, 1, 0, 3, 1, 1 );
lcd.slider( 22, 80, 0, 140, 25, 1, 255, 1, 0, 1); //Slider must be at top to appear
// Will be used for volume later on
lcd.string( 1, "1" ); // stringId 1
lcd.button( 1, 0, 150, 40, 30, 1, 0, 3, 1, 1 );
lcd.string( 2, "2" ); // stringId 1
lcd.button( 2, 40, 150, 40, 30, 1, 0, 3, 1, 2 );
lcd.string( 3, "3" ); // stringId 1
lcd.button( 3, 80, 150, 40, 30, 1, 0, 3, 1, 3 );
lcd.string( 4, "4" ); // stringId 1
lcd.button( 4, 0, 180, 40, 30, 1, 0, 3, 1, 4 );
lcd.string( 5, "5" ); // stringId 1
lcd.button( 5, 40, 180, 40, 30, 1, 0, 3, 1, 5 );
lcd.string( 6, "6" ); // stringId 1
lcd.button( 6, 80, 180, 40, 30, 1, 0, 3, 1, 6 );
lcd.string( 7, "7" ); // stringId 1
lcd.button( 7, 0, 210, 40, 30, 1, 0, 3, 1, 7 );
lcd.string( 8, "8" ); // stringId 1
lcd.button( 8, 40, 210, 40, 30, 1, 0, 3, 1, 8 );
lcd.string( 9, "9" ); // stringId 1
lcd.button( 9, 80, 210, 40, 30, 1, 0, 3, 1, 9 );
lcd.string( 10, "*" ); // stringId 1
lcd.button( 10, 120, 150, 40, 30, 1, 0, 3, 1, 10 );
lcd.string( 11, "0" ); // stringId 1
lcd.button( 11, 120, 180, 40, 30, 1, 0, 3, 1, 11 );
lcd.string( 12, "#" ); // stringId 1
lcd.button( 12, 120, 210, 40, 30, 1, 0, 3, 1, 12 );
lcd.string( 13, "MENU" ); // stringId 1
lcd.button( 13, 160, 150, 50, 30 , 1, 0, 3, 3, 13 );
lcd.string( 14, "Esc" ); // stringId 1
lcd.button( 14, 160, 180, 50, 30, 1, 0, 3, 3, 14 );
lcd.string( 15, "ENT" ); // stringId 1
lcd.button( 15, 160, 210, 50, 30, 1, 0, 3, 1, 15 );
lcd.string( 16, "TUNE UP" ); // stringId 1
lcd.button( 16, 210, 150, 110, 45, 1, 0, 3, 1, 16 );
lcd.string( 17, "TUNE DOWN" ); // stringId 1
lcd.button( 17, 210, 195, 110, 45, 1, 0, 3, 1, 17 );
// the problematic touch zones...everything else seems to work normally
lcd.touchZone( 18, 5, 110, 30, 40, 1);
lcd.touchZone( 19, 85, 110, 30, 40, 1);
lcd.touchZone( 20, 165, 110, 30, 40, 1);
lcd.touchZone( 21, 245, 110, 30, 40, 1);
Serial2.write(specialReports,9); // starts up the aux serial port
}
void loop()
{
int touch = touch;
touch = lcd.wstack(0);
if (( lcd.currentWidget == 1 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button1,10);
}
else if (( lcd.currentWidget == 1 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 2 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button2,10);
}
else if (( lcd.currentWidget == 2 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 3 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button3,10);
}
else if (( lcd.currentWidget == 3 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 4 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button4,10);
}
else if (( lcd.currentWidget == 4 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 5 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button5,10);
}
else if (( lcd.currentWidget == 5 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 6 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button6,10);
}
else if (( lcd.currentWidget == 6 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 7 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button7,10);
}
else if (( lcd.currentWidget == 7 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 8 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button8,10);
}
else if (( lcd.currentWidget == 8 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 9 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button9,10);
}
else if (( lcd.currentWidget == 9 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 10 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(buttonAsterisk,10);
}
else if (( lcd.currentWidget == 10 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 11 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(button0,10);
}
else if (( lcd.currentWidget == 11 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 12 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(buttonPound,10);
}
else if (( lcd.currentWidget == 12 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 13 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(buttonMENU,10);
}
else if (( lcd.currentWidget == 13 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonPesc,10);
}
if (( lcd.currentWidget == 14 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(buttonPesc,10);
}
else if (( lcd.currentWidget == 14 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 15 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(buttonEnter,10);
}
else if (( lcd.currentWidget == 15 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 16 )&& ( lcd.currentInfo == PRESSED )) { //tune up button command
delay(2);
Serial2.write(tuneUp,10);
}
else if (( lcd.currentWidget == 16 )&& ( lcd.currentInfo == RELEASED )) { //button release command so radio doesn't free run
delay(2);
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 17 )&& ( lcd.currentInfo == PRESSED )) { //tune up button command
delay(2);
Serial2.write(tuneDown,10);
}
else if (( lcd.currentWidget == 17 )&& ( lcd.currentInfo == RELEASED )) { //button release command so radio doesn't free run
delay(2);
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 18 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(f1Key,10);
}
else if (( lcd.currentWidget == 18 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 19 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(f2Key,10);
}
else if (( lcd.currentWidget == 19 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 20 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(fThreeKey,10);
}
else if (( lcd.currentWidget == 20 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (( lcd.currentWidget == 21 )&& ( lcd.currentInfo == PRESSED )){
Serial2.write(fFourKey,10);
}
else if (( lcd.currentWidget == 21 )&& ( lcd.currentInfo == RELEASED )) {
Serial2.write(buttonRelease,10);
}
if (Serial2.available()) {
int i=0;
for (i=0;i<30;i++) { // read the entire packet into rxdata
delay(5);
rxdata[i] = Serial2.read();
//rxdata[i+1] = '\0';
}
}
int L;
packetBegin = rxdata[0];
packetLength = rxdata[1];
appendedLength = rxdata[7];// for ack appended to incoming packet that skews offsets
opCode = rxdata[3];
subopCode = rxdata[4];
L = packetLength;
//if (rxdata[L+4] == 0x03 && rxdata[2] != 0x80) {
//if (rxdata[0] == 0x24){
//delay(25);
// Serial2.write(acknowledge,6);
//}
//else if (rxdata[2] == 0x80 && appendedLength+0x04 == 0x03){
// Serial2.write(acknowledge,6);
//}
if (packetBegin == 0x24) {
delay(22);
Serial2.write(acknowledge,6);
}
if (rxdata[2] == 0x80){
opCode = rxdata[9];
subopCode = rxdata[10];
}
if (opCode == 0x2E && subopCode == 0x02 && rxdata[2] != 0x80){ // menu
lcd.color(DARKSLATEGRAY);//background color
lcd.xy(0,0);
lcd.box(80,25,FILL);
lcd.color(YELLOW);
lcd.font(0);
lcd.xy(0,0);
lcd.print(rxdata[7]);
lcd.print(rxdata[8]);
lcd.print(rxdata[9]);
lcd.print(rxdata[10]);
lcd.print(rxdata[11]);
lcd.xy(0,0);
}
// for ack appended to incoming packet that skews offsets
else if (opCode == 0x2E && subopCode == 0x02 && rxdata[2] == 0x80){
lcd.color(DARKSLATEGRAY);//background color
lcd.xy(0,0);
lcd.box(80,25,FILL);
lcd.color(LIME);
lcd.font(0);
lcd.xy(0,0);
lcd.print(rxdata[13]);
lcd.print(rxdata[14]);
lcd.print(rxdata[15]);
lcd.print(rxdata[16]);
lcd.print(rxdata[17]);
lcd.xy(0,0);
}
if (opCode == 0x2E && subopCode == 0x03 && rxdata[2] != 0x80) { //frequency display
lcd.color(BLACK);
lcd.xy(0,50);
lcd.box(319,55,FILL);
lcd.color(YELLOW);
lcd.font("VER37");
lcd.xy(0,50);
lcd.print(rxdata[7]);
lcd.print(rxdata[8]);
lcd.print(rxdata[9]);
lcd.print(rxdata[10]);
lcd.print(rxdata[11]);
lcd.print(rxdata[12]);
lcd.print(rxdata[13]);
lcd.print(rxdata[14]);
lcd.print(rxdata[15]);
lcd.print(rxdata[16]);
lcd.print(rxdata[17]);
lcd.xy(0,50);
}
// for ack appended to incoming packet that skews offsets
if (opCode == 0x2E && subopCode == 0x03 && rxdata[2] == 0x80) { // alt frequency display for skewed offsets due to pre-pended junk ack packet
lcd.color(BLACK);
lcd.xy(0,50);
lcd.box(319,55,FILL);
lcd.color(YELLOW);
lcd.font("VER37");
lcd.xy(0,50);
lcd.print(rxdata[13]);
lcd.print(rxdata[14]);
lcd.print(rxdata[15]);
lcd.print(rxdata[16]);
lcd.print(rxdata[17]);
lcd.print(rxdata[18]);
lcd.print(rxdata[19]);
lcd.print(rxdata[20]);
lcd.print(rxdata[21]);
lcd.print(rxdata[22]);
lcd.print(rxdata[23]);
lcd.xy(0,50);
}
if (opCode == 0x2E && subopCode == 0x04) { // soft buttons where the touch zones will be
lcd.color(BLACK);
lcd.xy(0,115);
lcd.box(319,20,FILL);
lcd.color(LIME);
lcd.font(0);
lcd.xy(20,115);
lcd.print(rxdata[7]);
lcd.print(rxdata[8]);
lcd.print(rxdata[9]);
lcd.print(rxdata[10]);
lcd.xy(100,115);
lcd.print(rxdata[11]);
lcd.print(rxdata[12]);
lcd.print(rxdata[13]);
lcd.print(rxdata[14]);
lcd.xy(180,115);
lcd.print(rxdata[15]);
lcd.print(rxdata[16]);
lcd.print(rxdata[17]);
lcd.print(rxdata[18]);
lcd.xy(260,115);
lcd.print(rxdata[19]);
lcd.print(rxdata[20]);
lcd.print(rxdata[21]);
//lcd.print(rxdata[22]);
lcd.xy(0,110);
}
rxdata[L+4] = 0xFF; // these reset the opcodes and prevent reprinting when
rxdata[3] = 0xFF; // the radio is idle and there is no incoming data
rxdata[4] = 0xFF;
rxdata[0] = 0xFF;
}