#platform "uLCD-32PT_GFX2"

// This program reads a Dallas uFPU64 clock chip
// connected to the I2C port. The time is shown as a
// "digital style" 7 segment representation of a clock.
// The time can be set with the keypad, checking is
// done to ensure that the set time is legal.
// The demo uses GFX2DEMO.GCI to make it easy to get
// going, however it would look much nicer with some
// better graphical elements.

#inherit "4DGL_16bitColours.fnc"
#inherit "fops.inc"
// Ensure that GFX2DEMO.GCI and GFX2DEMO.DAT are installed on the FAT16 formatted uSD card. These files were
// created by the Graphics Composer  the Workshop subfolder \4D Labs\PICASO GFX2\COPY TO DISK, If image control
// mode 2 is used, the images must reside in a partition created, with RMPET.exe, in which case, the GCI file
// is prepared in RAW mode using Graphics Composer, and most reside at the agreed partition address.

#constant ICMODE 0      // leanest memory usage, slowest operation, seeks to each image. Adequate for most purposes.
//#constant ICMODE 1      // requires about 560 bytes for FAT buffer and disk structure, maps the cluster addresses, fastr than mode0.
//#constant ICMODE 2      // ultra fast raw mode, used in special circumstances where image refresh speed is important.

#constant FALSE, TRUE   // FALSE=0, TRUE=1


// images in GFX2DEMO.GCI
/*
0   "7segOrange_18x36.gif" 0000 0000
1   "keypad.gif" 3800 0000
2   "15x19dwn.bmp" 9E00 0001
3   "15x19up.bmp" A200 0001
4   "95EXIT.BMP" A600 0001
5   "95MAXBX.BMP" A800 0001
6   "95maxbx2.bmp" AA00 0001
7   "95MINBX.BMP" AC00 0001
8   "ADDBTTN.BMP" AE00 0001
9   "arrw05_01a.gif" B400 0001
10  "arrw05_11a.gif" BC00 0001
11  "arrw05_21a.gif" C400 0001
12  "arrw05_31a.gif" CC00 0001
13  "BLANK5.BMP" D400 0001
14  "books04.gif" DA00 0001
15  "CHECK.BMP" E400 0001
16  "chip02.gif" EC00 0001
17  "directry.gif" F600 0001
18  "graph03.gif" 0000 0002
19  "graph07.gif" 0A00 0002
20  "LBTTN.BMP" 1400 0002
21  "LEFTBTTN.BMP" 1A00 0002
22  "MAXBX.BMP" 1E00 0002
23  "MINBX.BMP" 2200 0002
24  "RBTTN.BMP" 2600 0002
25  "RGHTBTTN.BMP" 2C00 0002
26  "SPEAKER.BMP" 3000 0002
27  "TIME.BMP" 3600 0002
28  "10-gear.gif" 3C00 0002
29  "Catonthecob.gif" 3E00 0003
30  "Unicorn.gif" 2C00 0012
31  "Catonthecob.gif" 9600 0012
32  "Unicorn.gif" 5800 0049
33  "Scotland Map.jpg" DA00 004F
34  "backdrop8-240x320.jpg" 4E00 0050
35  "backdrop7-240x320.jpg" B000 0050
36  "backdrop6-240x320.jpg" 1200 0051
37  "backdrop5-240x320.jpg" 7400 0051
38  "backdrop4-240x320.jpg" D600 0051
39  "backdrop3-240x320.jpg" 3800 0052
40  "backdrop2-240x320.jpg" 9A00 0052
41  "bahamas.bmp" FC00 0052
41  "backdrop1-240x320.jpg" 5E00 0053
43  "hibiscus_hkowya9a.jpg" C000 0053
44  "sunset_q4l1iowt.jpg" 2200 0054
45  "strawberry_3db7f143.jpg" 8400 0054
46  "aeon041114.jpg" E600 0054
47  "pullup.mpeg" 4800 0055
48  "Scotland Map.jpg" 4A00 00D2
*/

// image labels for what we use in GFX2DEMO.GCI (image control indexes)
#constant SEG7      0
#constant KEYPAD    1
#constant EXITBTN   4
#constant ADDBTN    8
#constant CHECKBTN  15
#constant LFTBTN    21
#constant CLOCKBTN  27
#constant SECONDS   0       //indicies to clock.time
#constant MINUTES   1
#constant HOURS     2
#constant DAYS      0       //indicies to calendar.date
#constant MONTHS    1
#constant YEARS     2
// clock chip registers
//-------------------- uM-FPU Register Definitions -----------------------------
#constant REGYEAR    10                      // uM-FPU register
#constant REGMONTH   11                      // uM-FPU register
#constant REGDAY     12                      // uM-FPU register
#constant REGHOUR    13                      // uM-FPU register
#constant REGMINUTE  14                      // uM-FPU register
#constant REGSECOND  15                      // uM-FPU register
#constant REGTEMP    16                     //uM-FPU register
#constant uFPU64        0xC8            // I2C address of uFPU64
#constant WR            1               // 0 write 1 read

#constant SEG7_BG_COLOUR 0x0841     // 7 seg display background colour


var iHndl;                      // image control handle
var mx, my;                     // mouse/touch position
var tedstate;                    // clock edit state, 1=HH, 2=MM, 3=SS
var dedstate;                   // calendar edit state 1=YY, 2=MM, 3=DD
var hFile;
func bin2bcd()                                  // uses uFPU64 to
    write2byte(0,SELECTA,REGTEMP);              // convert byte in REGTEMP to 2 digit BCD
    write2byte(0,LUDIVI,10);
    write2byte(0,LMULI,16);                     // move tens digit to HI nibble
    write2byte(0,LADD, 0);                      // add in remainder for LO nibble
endfunc
func bcd2bin(var binValue)                      // convert a 2 digit BCD value into its hex/binary single byte equivalent
    return (binValue>>4)*10 + (binValue&15);
endfunc
func readbyte(var address)                      // read a single byte from the required register on the uFPU64
    var b;
    I2C_Start();                                // Generate Start condition
    I2C_Write(uFPU64);                          // send slave address
    I2C_Write(LObyte(address));                 // Send register address
    I2C_Stop();                                 // generate a stop
    I2C_Start();                                // Generate start
    I2C_Write(uFPU64+WR);                       // send control byte for Read
    b := I2C_Read();                            // read the byte
    I2C_Nack();                                 // finished reading, send Not Ack
    I2C_Stop();                                 // Send Stop Condition
    return b;                                   // return the register value
endfunc

func writebyte(var register, var value)         // write a single byte to the required register on the uFPU64
    I2C_Start();                                // Generate Start condition
    I2C_Write(uFPU64);                          // send slave address
    I2C_Write(register);                        // select the register
    I2C_Write(value);                           // save the value in selected register
    I2C_Stop();                                 // finished with bus
endfunc

func write2byte(var register, var value1, var value2)// write 2 bytes to the required register on the uFPU64
    I2C_Start();                                // Generate Start condition
    I2C_Write(uFPU64);                          // send slave address
    I2C_Write(register);                        // select the register
    I2C_Write(value1);                           // save the value in selected register
    I2C_Write(value2);                           // save the value in selected register
    I2C_Stop();                                 // finished with bus
endfunc
func write3byte(var register, var value1, var value2, var value3)// write 3 bytes to the required register uFPU64
    I2C_Start();                                // Generate Start condition
    I2C_Write(uFPU64);                          // send slave address
    I2C_Write(register);                        // select the register
    I2C_Write(value1);                           // save the value in selected register
    I2C_Write(value2);                           // save the value in selected register
    I2C_Write(value3);                           // save the value in selected register
    I2C_Stop();                                 // finished with bus
endfunc
func printstring()                              // print the string pointed to by the 0 reg uFPU64
    var     c;
    var     ccount;
    writebyte(0,READSTR);
    I2C_Start();                                // Generate Start condition
    I2C_Write(uFPU64);                          // send slave address
    I2C_Write(0);                               // Send register address
    I2C_Stop();
    I2C_Start();                                // Generate start
    I2C_Write(uFPU64+WR);                       // send control byte for Read
    pause(2);
    c:=0x31;                                    // set c == a non-zero value
    ccount := 20;                               // max length 20 bytes
    while(c!=0)
         c:=I2C_Read();
         if(c==0)                               // end of string if c == 0
            I2C_Nack();                         // signal last byte read
            break;                              // exit read loop
         endif
         I2C_Ack();                             // signal read success

         pause(10);
         print([CHR] c);                        // print on uLCD screen
    wend
    I2C_Stop();                                 // Send Stop Condition
endfunc
// map of key values for keypad
#DATA
    byte keys 7,8,9,4,5,6,1,2,3,0,0,0
#END

// max time register value for edit check
#DATA
    byte maxtime 0x59,0x59,0x23
#END
#DATA
    byte maxdate 0x31,0x12,0x99
#END
// translate edit positions to required register
#DATA
    word timexlat HOURS,MINUTES,SECONDS
#END
#DATA
    word datexlat YEARS,MONTHS,DAYS
#END
func TimeKeypad(var state)
    var private tcharpos;
    var temp,r,n,x,y,k,x1,y1,xoffs,yoffs,oldshadow;
    var private tkeyval;

    if(!tedstate)
        tcharpos := 2;
        oldshadow := gfx_Set(BEVEL_SHADOW,1);
        img_Darken(iHndl, KEYPAD);
        img_SetAttributes(iHndl, KEYPAD, I_TOUCH_DISABLE);      // disable keypad touch
        img_SetWord(iHndl, KEYPAD, IMAGE_INDEX, 10);            // set 10th frame, button up (non pressed) state
        gfx_Set(BEVEL_SHADOW,oldshadow);
    else
        img_ClearAttributes(iHndl, KEYPAD, I_TOUCH_DISABLE);    // enable keypad touch
        tkeyval := 10;                                           // initially, assume no key pressed, select last frame
        if(state == TOUCH_PRESSED)
            x1 := 44;
            y1 := 169;
            xoffs := 16;                                        // we know where the keypad is, just use fixed values to save codespace
            yoffs := 16;
            for(y := y1; y < y1 + yoffs * 4;y += yoffs)         // now find touch co-ord
                for(x := x1; x < x1 + xoffs * 3; x += xoffs)
                    n++;
                    if(mx > x && mx < x + xoffs && my > y && my < y + yoffs) k := n;
                next
                if(k) break;
            next
            if(k)                                               // if we got a valid key
                tkeyval := keys[k - 1];                          // get the key val
                r := timexlat[tedstate - 1];                         // point to correct register
                temp := Clock.time[r];                          // shift and add new digit
                temp := ((temp << 4) & 0xF0) + tkeyval;
                Clock.time[r] := temp;
                Clock.edit &= ~(tcharpos << ((tedstate-1) << 1)); // modify the underscore
                tcharpos := 1;
                Clock();
                // update 7seg display
            endif
        endif
        img_SetWord(iHndl, KEYPAD, IMAGE_INDEX, tkeyval);        // set required frame, if 10th frame, its the button up (non pressed) state
    endif
    img_Show(iHndl, KEYPAD);


endfunc
func DateKeypad(var state)
    var private dcharpos;
    var temp,r,n,x,y,k,x1,y1,xoffs,yoffs,oldshadow;
    var private dkeyval;

    if(!dedstate)
        dcharpos := 2;
        oldshadow := gfx_Set(BEVEL_SHADOW,1);
        img_Darken(iHndl, KEYPAD);
        img_SetAttributes(iHndl, KEYPAD, I_TOUCH_DISABLE);      // disable keypad touch
        img_SetWord(iHndl, KEYPAD, IMAGE_INDEX, 10);            // set 10th frame, button up (non pressed) state
        gfx_Set(BEVEL_SHADOW,oldshadow);
    else
        img_ClearAttributes(iHndl, KEYPAD, I_TOUCH_DISABLE);    // enable keypad touch
        dkeyval := 10;                                           // initially, assume no key pressed, select last frame
        if(state == TOUCH_PRESSED)
            x1 := 44;
            y1 := 169;
            xoffs := 16;                                        // we know where the keypad is, just use fixed values to save codespace
            yoffs := 16;
            for(y := y1; y < y1 + yoffs * 4;y += yoffs)         // now find touch co-ord
                for(x := x1; x < x1 + xoffs * 3; x += xoffs)
                    n++;
                    if(mx > x && mx < x + xoffs && my > y && my < y + yoffs) k := n;
                next
                if(k) break;
            next
            if(k)                                               // if we got a valid key
                dkeyval := keys[k - 1];                          // get the key val
                r := datexlat[dedstate - 1];                         // point to correct register
                temp := Calendar.date[r];                          // shift and add new digit
                temp := ((temp << 4) & 0xF0) + dkeyval;
                Calendar.date[r] := temp;
                Calendar.dedit &= ~(dcharpos << ((dedstate-1) << 1)); // modify the underscore
                dcharpos := 1;
                Calendar();
                // update 7seg display
            endif

        endif
        img_SetWord(iHndl, KEYPAD, IMAGE_INDEX, dkeyval);        // set required frame, if 10th frame, its the button up (non pressed) state
    endif
    img_Show(iHndl, KEYPAD);

endfunc
// show time normally if edit==0, else show required underscore.
// each bit in var edit coresponds to an underline displayed, bit5 is
// digit 1 downto bit 0 = digit 6
func Clock()
    var private edit;                                           // editing mode, bits 5:0 selects uderscores for digits 6:1
    var private time[6];                                        // time in BCD format, coresponds to clock registers SECONDS,MINUTES,HOURS,DAYS,MONTHS,YEARS
    var k, n, xpos, regptr;

    #constant X 22                                              // x position for time
    #constant Y 40                                              // y position for time
    #constant W 22                                              // digit width


    img_Enable(iHndl, SEG7);                                    // enable the 7seg display while we display it
    xpos := X;                                                  // set starting x
    regptr := HOURS;                                            // start at hours
    while(n < 6)
        img_SetPosition(iHndl, SEG7, xpos, Y);                  // set position for digit
        if((edit>>n)&1)                                         // if editing digit,
            k := 11;                                            // select underscore character
        else
            k := time[regptr];                                  // else get required time register
            if(!(n & 1)) k := k >> 4;                           // get HI nibble if HI digit
        endif
        img_SetWord(iHndl, SEG7, IMAGE_INDEX, k&15);            // select required digit

        img_Show(iHndl, SEG7);                                  // show the image
        xpos += W;
        n++;
        if(n == 2 || n == 4)                                    // when required,
            regptr--;                                           // decrement register pointer
            xpos += 4;
            gfx_RectangleFilled(xpos, Y + 10,xpos + 4, Y + 14,ORANGE);  // place colon
            gfx_RectangleFilled(xpos, Y + 20,xpos + 4, Y + 24,ORANGE);
            xpos += 10;
        endif
    wend
    img_Disable(iHndl, SEG7);                                   // we're done displaying, disable the 7seg display

endfunc
// show date normally if edit==0, else show required underscore.
// each bit in var edit coresponds to an underline displayed, bit5 is
// digit 1 downto bit 0 = digit 6
func Calendar()
    var private dedit;                                           // editing mode, bits 5:0 selects uderscores for digits 6:1
    var private date[6];                                        // date in BCD format, coresponds to clock registers DAYS,MONTHS,YEARS
    var k, n, xpos, regptr;

    #constant X 22                                              // x position for time
    #constant Y 110                                              // y position for time
    #constant W 22                                              // digit width


    img_Enable(iHndl, SEG7);                                    // enable the 7seg display while we display it
    xpos := X;                                                  // set starting x
    regptr := YEARS;                                            // start at month
    while(n < 6)
        img_SetPosition(iHndl, SEG7, xpos, Y);                  // set position for digit
        if((dedit>>n)&1)                                         // if editing digit,
            k := 11;                                            // select underscore character
        else
            k := date[regptr];                                  // else get required date register
            if(!(n & 1)) k := k >> 4;                           // get HI nibble if HI digit
            //print("k= ",[HEX2] k);
        endif
        img_SetWord(iHndl, SEG7, IMAGE_INDEX,k&15);            // select required digit

        img_Show(iHndl, SEG7);                                  // show the image
        xpos += W;
        n++;
        if(n == 2 || n == 4)                                    // when required,
            regptr--;                                           // decrement register pointer
            xpos += 4;
            gfx_RectangleFilled(xpos, Y + 10,xpos + 4, Y + 24,ORANGE);  // place colon
//            gfx_RectangleFilled(xpos, Y + 20,xpos + 4, Y + 24,ORANGE);
            xpos += 10;
        endif
    wend
    img_Disable(iHndl, SEG7);                                   // we're done displaying, disable the 7seg display

endfunc
func checkClockRegisters()
    var reg, retval:=TRUE;
    if(tedstate)
        reg := timexlat[tedstate-1];
        if(Clock.time[reg] > maxtime[reg])           // check for sensible value
            gfx_MoveTo(90,7);
            txt_FGcolour(RED);                      // if not, throw the message
            putstr("TIME ERROR\r");
            pause(500);
            putstr("     ");
            tedstate--;                              // and backup so we stay in current edit field
            retval := FALSE;
        endif
    endif
    return retval;
endfunc

func checkDateRegisters()
    var reg, retval:=TRUE;
    if(dedstate)
        reg := datexlat[dedstate-1];
        if(Calendar.date[reg] > maxdate[reg])           // check for sensible value
            gfx_MoveTo(150,7);
            txt_FGcolour(RED);                      // if not, throw the message
            putstr("DATE ERROR\r");
            pause(500);
            putstr("     ");
            dedstate--;                              // and backup so we stay in current edit field
            retval := FALSE;
        endif
    endif
    return retval;
endfunc
func main()
    var TIMEEDIT := FALSE;
    var DATEEDIT := FALSE;
    var n, c, colr:=RED;
    var state;
    var exit;
    var Action;
    var ss, tt;
    var retry := 10;
    while(retry-- && !file_Mount());                                // mount the drive
    if (!retry)
        putstr("Mount Failed!");
        pause(2000);
        return;                                                     // exit if can't mount
    endif
//    gfx_ScreenMode(LANDSCAPE);
    iHndl := file_LoadImageControl("GFX2DEMO.DAT", "GFX2DEMO.GCI", ICMODE);  // build the image control using required mode, returning a pointer to the structure allocation
    if (!iHndl)
        pause(2000);
        return;                                                     // exit if can't load image control
    endif

    I2C_Open(I2C_SLOW);                                             // 100khz
    //I2C_Open(I2C_MED);                                            // 400khz
    //I2C_Open(I2C_FAST);                                           // 1mhz NB uFPU64 may not run at 1mhz!!!

    pause(10);
    writebyte(1,0);                            // reset the uFPU by writing a 0 to register 1
    pause(50);                                 // wait for the FPU64 to complete the reset
// send a SYNC commnad
    writebyte(0,SYNC);                          // make sure syncronization is in place
// to enable debug uncomment the following code - to see if communication with uFPU is in place
/*
    c:=readbyte(0);                             // should be 0x5C
    txt_FontID(FONT2);
    txt_MoveCursor(2,3);
    txt_FGcolour(WHITE);
    print("Sync byte returned = ", [HEX2] c);
    pause(500);
// try getting version next
    print("\r\nVersion = ");
    writebyte(0,VERSION);
    printstring();
    print("\r\n");
    pause(500);
*/
// initialize the RTC

    Action := START;
    write2byte(0,RTC,Action);           // start the RTC
    Action := READ_TIME + FPUSTR;
    write2byte(0,RTC,Action);            // read the date and time as a string
    writebyte(0,READSTR);        // print the string
    printstring();
    pause(500);                         //make sure we have a time
    gfx_Cls();
    tedstate := 0;
    dedstate := 0;
    Clock.edit := 0;
    Calendar.dedit := 0;
    img_Disable(iHndl, ALL);                                        // first up, disable all the images

    // now enable what we need
    img_Enable(iHndl, KEYPAD);                                      // we want the keypad
    img_Enable(iHndl, EXITBTN);                                     // we want the exit button
    img_Enable(iHndl, CLOCKBTN);                                    // we want the time button
    img_Enable(iHndl, ADDBTN);                                      // we want the add button for date edit




    //gfx_Origin(30,15);

    gfx_Panel(PANEL_RAISED,0, 0, 200, 25, DARKBLUE);                // title bar
    gfx_Panel(PANEL_RAISED,0, 26, 200, 250,GRAY);                   // main window panel
    img_SetPosition(iHndl, EXITBTN, 184, 6);                        // place the exit button
    gfx_MoveTo(8,7);
    txt_Opacity(OPAQUE);
    txt_BGcolour(DARKBLUE);
    txt_FGcolour(CYAN);
    putstr("Set Time and date");                                             // place the title

    // 7 seg display panel
    gfx_Panel(PANEL_SUNKEN,15, 32, 170, 50, GRAY);
    gfx_Panel(PANEL_RAISED,19, 36, 162, 42, SEG7_BG_COLOUR);
     gfx_Panel(PANEL_SUNKEN,15, 102, 170, 50, GRAY);
    gfx_Panel(PANEL_RAISED,19, 106, 162, 42, SEG7_BG_COLOUR);

    img_SetPosition(iHndl, KEYPAD, 40, 165);                         // place the keypad
    img_SetPosition(iHndl, CLOCKBTN, 140, 170);                      // place the time button
    img_SetPosition(iHndl, ADDBTN, 170, 170);                      // place the time button
    img_SetPosition(iHndl, CHECKBTN, 138, 210);                     // place the check button (hidden until editing)
    img_SetPosition(iHndl, LFTBTN, 170, 210);


    img_Show(iHndl, ALL);                                           // update images
    gfx_Rectangle(140, 110, 163, 121, RED);                          // place RED rectangle around clock button (locked state)

 //   Keypad(0);



    touch_Set(TOUCH_ENABLE);                                        // enable the touch screen
    pause(1000);
    while(!exit)                                                    // stay in loop til quit button hit

        if((Clock.edit == 0 && tedstate == 0) &&(Calendar.dedit ==0 && dedstate ==0))                        // if we're not editing
            Action := READ_TIME+SECOND;
            write2byte(0,RTC,Action);                                       // seconds are in reg 0
            write2byte(0,COPY0, REGSECOND);                                 // REGSECOND is binary
            write2byte(0,COPY0, REGTEMP);                                      // convert to BCD
            bin2bcd();
            writebyte(0,LREADBYTE);
            ss := readbyte(0);
    //        print("ss= ",[HEX2] ss);
            Clock.time[SECONDS] := ss;
            Action := READ_TIME+MINUTE;
            write2byte(0,RTC,Action);
            write2byte(0,COPY0, REGMINUTE);
            write2byte(0,COPY0, REGTEMP);                                      // convert to BCD
            bin2bcd();
            writebyte(0,LREADBYTE);
            ss := readbyte(0);
            Clock.time[MINUTES] := ss;
            Action := READ_TIME+HOUR;
            write2byte(0,RTC,Action);
            write2byte(0,COPY0, REGHOUR);
            write2byte(0,COPY0, REGTEMP);                                      // convert to BCD
            bin2bcd();
            writebyte(0,LREADBYTE);
            ss := readbyte(0);
            Clock.time[HOURS] := ss;
            Clock();

            Action := READ_TIME+MONTH;
            write2byte(0,RTC,Action);                                       // seconds are in reg 0
            write2byte(0,COPY0, REGMONTH);                                 // REGSECOND is binary
            write2byte(0,COPY0, REGTEMP);                                      // convert to BCD
            bin2bcd();
            writebyte(0,LREADBYTE);
            ss := readbyte(0);
 //           print("ss= ",[HEX2] ss);
            Calendar.date[MONTHS] := ss;

            Action := READ_TIME+DAY;
            write2byte(0,RTC,Action);
            write2byte(0,COPY0, REGDAY);
            write2byte(0,COPY0, REGTEMP);                                      // convert to BCD
            bin2bcd();
            writebyte(0,LREADBYTE);
            ss := readbyte(0);
            Calendar.date[DAYS] := ss;

            Action := READ_TIME+YEAR;
            write2byte(0,RTC,Action);
            write2byte(0,COPY0, REGYEAR);
            write2byte(0,COPY0, REGTEMP);                                      // convert to BCD
            bin2bcd();
            writebyte(0,LREADBYTE);
            ss := readbyte(0);
            Calendar.date[YEARS] := ss;
            Calendar();                                            // update the date
        endif

        state := touch_Get(TOUCH_STATUS);                           // we'll look for any touch activity
        mx := touch_Get(TOUCH_GETX);                                // we'll also grab the x
        my := touch_Get(TOUCH_GETY);                                // and the y coordinates of the touch

        if(state == TOUCH_PRESSED)                                  // if there's a press
            n := img_Touched(iHndl, ALL);                           // see if any images were touched
            if (n != -1)
                if(n == KEYPAD && TIMEEDIT == TRUE)                                     // if keypad was touched,
                    TimeKeypad(state);                                  // update keypad
                endif
                if (n==KEYPAD && DATEEDIT == TRUE)
                    DateKeypad(state);
                endif
                if(n!= KEYPAD)
                  img_Lighten(iHndl, n);                            // else just lighten when we touch
                  img_Show(iHndl, n);
                endif
            endif
        endif
           // gfx_Rectangle(140, 90, 163, 111, colr);                 // place rectangle round clock btn


        if(state ==  TOUCH_RELEASED)                                // if there's a release;
            if (n != -1)

                if(n==EXITBTN)
                    exit := 1;                                           // exit if exit button hit
                endif
                if(n==CHECKBTN)                                                     // if check button hit
                    if(checkClockRegisters())                                            // if last edit was ok
                        Action := INIT;
                        write2byte(0,RTC,Action);            // initialize the RTC
                        Action := STOP;
                        ss := Calendar.date[YEARS];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);        /* load bin years into reg0 */
                        Action := WRITE_TIME + YEAR;
                        write2byte(0,RTC,Action);            // write the year to the RTC
                        ss := Calendar.date[MONTHS];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);        /* load bin hours into reg0 */
                        Action := WRITE_TIME + MONTH;
                        write2byte(0,RTC,Action);            // write the hour to the RTC
                        ss := Calendar.date[DAYS];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);        /* load bin days into reg0 */
                        Action := WRITE_TIME + DAY;
                        write2byte(0,RTC,Action);            // write the day to the RTC
                        ss := Clock.time[HOURS];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);        /* load bin hours into reg0 */
                        Action := WRITE_TIME + HOUR;
                        write2byte(0,RTC,Action);            // write the hour to the RTC
                        ss := Clock.time[MINUTES];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);            /* load bin minutes into reg0 */
                        Action := WRITE_TIME + MINUTE;
                        write2byte(0,RTC,Action);            // write the minutes to the RTC

                        ss := Clock.time[SECONDS];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);            /* load bin hours into reg0 */
                        Action := WRITE_TIME + SECOND;
                        write2byte(0,RTC,Action);            // write the seconds to the RTC
                        Action := START;
                        write2byte(0,RTC,Action);           // start the RTC
                        Clock.edit := 0;                                            // not editing now, run mode
                        tedstate := 0;
                        colr := RED;
                        img_Disable(iHndl, CHECKBTN);                               // disable check button
              //          gfx_RectangleFilled(138, 130, 138+28, 130+28, GRAY);        // erase the check button
                        Clock();

                        TimeKeypad(0);
                     else
                        n := CLOCKBTN;                                  // else error, redo current edit phase
                     endif
                endif

                if(n == CLOCKBTN)
                    TIMEEDIT := TRUE;
                    DATEEDIT := FALSE;
                    img_Darken(iHndl, CLOCKBTN);
                    img_Show(iHndl, CLOCKBTN);
                    checkClockRegisters();                                   // check for legal values
                    if(++tedstate == 4) tedstate := 1;                    // cycle through the edit fields
                    Clock.edit := 3 << ((tedstate-1) << 1);              // set required bits high in edit register
                    TimeKeypad.tcharpos := 2;                                // start edit at least significant digit
                    Clock.time[timexlat[tedstate-1]] := 0;                   // zero the holding register ready
                    img_Enable(iHndl, CHECKBTN);                        // enable check button
                    img_Show(iHndl, CHECKBTN);                          // display it
                    gfx_Rectangle(138, 130, 138+27, 130+27, GRAY);      // rectangle to get rid of those annoying alignment dots
                    colr := LIME;
                    Clock();
                    TimeKeypad(state);
                endif
                if(n == ADDBTN)
                    DATEEDIT := TRUE;
                    TIMEEDIT := FALSE;
                    img_Darken(iHndl, ADDBTN);
                    img_Show(iHndl, ADDBTN);
                   // checkDateRegisters();                                   // check for legal values
                    if(++dedstate == 4) dedstate := 1;                    // cycle through the edit fields
                    Calendar.dedit := 3 << ((dedstate-1) << 1);           // set required bits high in edit register
                    DateKeypad.dcharpos := 2;                                // start edit at least significant digit
                    Calendar.date[datexlat[dedstate-1]] := 0;                   // zero the holding register ready
                    img_Enable(iHndl, LFTBTN);                        // enable check button
                    img_Show(iHndl, LFTBTN);                          // display it
                    //gfx_Rectangle(138, 130, 138+27, 130+27, GRAY);      // rectangle to get rid of those annoying alignment dots
                    colr := LIME;
                    Calendar();
                    DateKeypad(state);
                endif
                 if(n==LFTBTN)                                                     // if check button hit
                    //if(checkDateRegisters())                                            // if last edit was ok
                        Action := INIT;
                        write2byte(0,RTC,Action);            // initialize the RTC
                        Action := STOP;
                        ss := Calendar.date[YEARS];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);        /* load bin years into reg0 */
                        Action := WRITE_TIME + YEAR;
                        write2byte(0,RTC,Action);            // write the year to the RTC
                        ss := Calendar.date[MONTHS];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);        /* load bin hours into reg0 */
                        Action := WRITE_TIME + MONTH;
                        write2byte(0,RTC,Action);            // write the hour to the RTC
                        ss := Calendar.date[DAYS];            // in BCD form
                        tt := bcd2bin(ss);
                        write2byte(0,LONGUBYTE, tt);        /* load bin days into reg0 */
                        Action := WRITE_TIME + DAY;
                        write2byte(0,RTC,Action);            // write the day to the RTC
                        Action := START;
                        write2byte(0,RTC,Action);           // start the RTC
                        Calendar.dedit := 0;                                            // not editing now, run mode
                        dedstate := 0;
                        colr := RED;
                        img_Disable(iHndl, LFTBTN);                               // disable check button
               //         gfx_RectangleFilled(138, 130, 138+28, 130+28, GRAY);        // erase the check button
                        Calendar();

                        DateKeypad(0);
                    // else
                    //    n := ADDBTN;                                  // else error, redo current edit phase
                    // endif
                endif

                if(n == KEYPAD&& TIMEEDIT== TRUE)                                         // if keypad release
                    TimeKeypad(state);                                      // update state
                endif
                if(n == KEYPAD&& DATEEDIT== TRUE)                                         // if keypad release
                    DateKeypad(state);                                      // update state
                endif
            endif
  //          gfx_Rectangle(140, 90, 163, 111, colr);      // place rectangle round clock btn
            n := -1;
       endif


    wend

endfunc

