//****************************************************************************
//
// KEYBOARD.C - Displays keyboard button presses on the LCD panel.
//
// Copyright (c) 1998-1999 Cirrus Logic, Inc.
//
//****************************************************************************
#include "../lib7209/lib7209.h"

//****************************************************************************
//
// The keyboard that comes with the EP7209 evaluation board is an 83-key
// keyboard with the following scan arrangement:
//
//           R0  R1  R2  R3  R4  R5  R6  R7  E0  E1  E2  E3  E4  E5  E6  E7
//        +---------------------------------------------------------------
//     C0 | esc   1 Tab CpL   \  Sp ArL ArU ArD ArR ShL Ctl  Fn Alt AGr ShR
//     C1 |  F5   6   T   G   B   /   ;   P   - F10
//     C2 |  F4   5   R   F   V Del   '   [   = Num
//     C3 |  F3   4   E   D   C Ins       ]  BS Prt
//     C4 |  F2   3   W   S   X     Ret   `     ScL
//     C5 |  F1   2   Q   A   Z End PgD PgU  Hm Brk
//     C6 |  F6   7   Y   H   N   .   L   O   0  F9
//     C7 |  F7   8   U   J   M   ,   K   I   9  F8
//
// Blanks in table are non-existant keys.  This table also corresponds (when
// read across the rows) to the order in which the keys appear in the array
// returned by KbdRead().
//
// This program will draw a graphic representation of the keyboard on the LCD
// screen and highlight the keys which are currently pressed.  Additionally,
// normal text keys will be printed in teletype fashion across the bottom of
// the LCD screen.
//
//****************************************************************************

void	entry(void);


void	entry(void){
    int iIdx1, iIdx2, iX, iY, iBL = 0;
    char cBuffer[128], cPressed[128], cChar;
    char cKeys[129] = "\0001\0\0\\ \0\0\0\0\0\0\0\0\0\0"
                      "\0006tgb/;p-\0\0\0\0\0\0\0"
                      "\0005rfv\0\'[=\0\0\0\0\0\0\0"
                      "\0004edc\0\0]\0\0\0\0\0\0\0\0"
                      "\0003wsx\0\0`\0\0\0\0\0\0\0\0"
                      "\0002qaz\0\0\0\0\0\0\0\0\0\0\0"
                      "\0007yhn.lo0\0\0\0\0\0\0\0"
                      "\0008ujm,ki9\0\0\0\0\0\0\0";
    char cKeysShift[129] = "\0!\0\0| \0\0\0\0\0\0\0\0\0\0"
                           "\0^TGB?:P_\0\0\0\0\0\0\0"
                           "\0%RFV\0\"{+\0\0\0\0\0\0\0"
                           "\0$EDC\0\0}\0\0\0\0\0\0\0\0"
                           "\0#WSX\0\0~\0\0\0\0\0\0\0\0"
                           "\0@QAZ\0\0\0\0\0\0\0\0\0\0\0"
                           "\0&YHN>LO)\0\0\0\0\0\0\0"
                           "\0*UJM<KI(\0\0\0\0\0\0\0";
    int iKeyXPos[128] = {   8,  16,   8,  10,  56, 104, 200, 216,
                          216, 232,  18,   8,  24,  40, 152, 198,
                           88,  96,  88,  92, 100, 180, 172, 168,
                          176, 168,   0,   0,   0,   0,   0,   0,
                           72,  80,  72,  76,  84, 184, 188, 184,
                          192, 184,   0,   0,   0,   0,   0,   0,
                           56,  64,  56,  60,  68, 168,   0, 200,
                          212, 200,   0,   0,   0,   0,   0,   0,
                           40,  48,  40,  44,  52,   0, 210, 216,
                            0, 216,   0,   0,   0,   0,   0,   0,
                           24,  32,  24,  28,  36, 232, 232, 232,
                          232, 232,   0,   0,   0,   0,   0,   0,
                          104, 112, 104, 108, 116, 164, 156, 152,
                          160, 152,   0,   0,   0,   0,   0,   0,
                          120, 128, 120, 124, 132, 148, 140, 136,
                          144, 136,   0,   0,   0,   0,   0,   0 };
    int iKeyYPos[128] = {  16,  32,  48,  64,  96,  96,  96,  80,
                           96,  96,  80,  96,  96,  96,  96,  80,
                           16,  32,  48,  64,  80,  80,  64,  48,
                           32,  16,   0,   0,   0,   0,   0,   0,
                           16,  32,  48,  64,  80,  96,  64,  48,
                           32,  16,   0,   0,   0,   0,   0,   0,
                           16,  32,  48,  64,  80,  96,   0,  48,
                           32,  16,   0,   0,   0,   0,   0,   0,
                           16,  32,  48,  64,  80,   0,  64,  48,
                            0,  16,   0,   0,   0,   0,   0,   0,
                           16,  32,  48,  64,  80,  80,  64,  48,
                           32,  16,   0,   0,   0,   0,   0,   0,
                           16,  32,  48,  64,  80,  80,  64,  48,
                           32,  16,   0,   0,   0,   0,   0,   0,
                           16,  32,  48,  64,  80,  80,  64,  48,
                           32,  16,   0,   0,   0,   0,   0,   0 };

    //
    // Enable the LCD controller, clear the frame buffer, and turn on the LCD
    // panel.
    //
    LCDEnable();
    LCDCls();
    LCDOn();

    //
    // Print instructions for the user on the LCD screen.
    //
    LCDPrintString("Press both shift keys to exit, break for backlighting.", 0,
                   0, 15);

    //
    // Draw a grid of boxes which represent the keyboard, with the same layout
    // as the keyboard.
    //
    for(iIdx1 = 0; iIdx1 < 128; iIdx1++)
    {
        //
        // Skip this key if it is not really a key.
        //
        if((iKeyXPos[iIdx1] == 0) && (iKeyYPos[iIdx1] == 0))
        {
            continue;
        }

        //
        // Draw a box around the location of this key.
        //
        LCDLine(iKeyXPos[iIdx1] - 8, iKeyYPos[iIdx1],
                iKeyXPos[iIdx1] + 8, iKeyYPos[iIdx1], 15);
        LCDLine(iKeyXPos[iIdx1] + 8, iKeyYPos[iIdx1],
                iKeyXPos[iIdx1] + 8, iKeyYPos[iIdx1] + 16, 15);
        LCDLine(iKeyXPos[iIdx1] + 8, iKeyYPos[iIdx1] + 16,
                iKeyXPos[iIdx1] - 8, iKeyYPos[iIdx1] + 16, 15);
        LCDLine(iKeyXPos[iIdx1] - 8, iKeyYPos[iIdx1] + 16,
                iKeyXPos[iIdx1] - 8, iKeyYPos[iIdx1], 15);
    }

    //
    // The initial cursor position for the typed text is (0, 208).
    //
    iX = 0;
    iY = 208;

    //
    // Clear the array of pressed buttons.
    //
    for(iIdx1 = 0; iIdx1 < 128; iIdx1++)
    {
        cPressed[iIdx1] = 0;
    }

    //
    // Read the keyboard and draw the pressed buttons until both shift keys are
    // pressed simultaneously.
    //
    while(1)
    {
        //
        // Read the current state of the keyboard button matrix.
        //
        KbdRead(cBuffer);

        //
        // If both shift keys are pressed, then bail out.
        //
        if(cBuffer[10] && cBuffer[15])
        {
            break;
        }

        //
        // Loop through the 8 columns on the keyboard matrix.
        //
        for(iIdx1 = 0; iIdx1 < 8; iIdx1++)
        {
            //
            // Loop through the 16 rows on the keyboard matrix.
            //
            for(iIdx2 = 0; iIdx2 < 16; iIdx2++)
            {
                //
                // See if the keyboard button at this row and column is
                // pressed.
                //
                if(cBuffer[(iIdx1 * 16) + iIdx2])
                {
                    //
                    // It is, so fill the corresponding square of the keyboard
                    // grid with a solid circle.
                    //
                    if(iKeyXPos[(iIdx1 * 16) + iIdx2] &&
                       iKeyYPos[(iIdx1 * 16) + iIdx2])
                    {
                        LCDFillCircle(iKeyXPos[(iIdx1 * 16) + iIdx2],
                                      iKeyYPos[(iIdx1 * 16) + iIdx2] + 8, 4,
                                      15);
                    }

                    //
                    // If this key was not pressed before, then print this
                    // character out on the bottom of the LCD screen if it is
                    // a text character.
                    //
                    if(!cPressed[(iIdx1 * 16) + iIdx2])
                    {
                        //
                        // Is this being shifted?
                        //
                        if(cBuffer[10] || cBuffer[15])
                        {
                            //
                            // Grab the ASCII representation of this key when
                            // it is shifted.
                            //
                            cChar = cKeysShift[(iIdx1 * 16) + iIdx2];
                        }
                        else
                        {
                            //
                            // Grab the ASCII representation of this key when
                            // it is un-shifted.
                            //
                            cChar = cKeys[(iIdx1 * 16) + iIdx2];
                        }

                        //
                        // If this is an actual ASCII character, then print it
                        // at the bottom of the LCD screen.
                        //
                        if(cChar)
                        {
                            //
                            // Print the character.
                            //
                            LCDPrintChar(cChar, iX, iY, 15);

                            //
                            // Advance the cursor.
                            //
                            iX += 8;
                            if(iX == 640)
                            {
                                iX = 0;
                                iY += 8;
                                if(iY == 240)
                                {
                                    iY = 208;
                                }
                            }
                        }

                        //
                        // If this is the break key, then flip the state of the
                        // backlighting.
                        //
                        if((iIdx1 == 5) && (iIdx2 == 9))
                        {
                            iBL ^= 1;
                            if(iBL)
                            {
                                LCDBacklightOn();
                            }
                            else
                            {
                                LCDBacklightOff();
                            }
                        }

                        //
                        // Mark this key as pressed.
                        //
                        cPressed[(iIdx1 * 16) + iIdx2] = 1;
                    }
                }
                else
                {
                    //
                    // It is not, so erase the corresponding square of the
                    // keyboard grid.
                    //
                    if(iKeyXPos[(iIdx1 * 16) + iIdx2] &&
                       iKeyYPos[(iIdx1 * 16) + iIdx2])
                    {
                        LCDFillCircle(iKeyXPos[(iIdx1 * 16) + iIdx2],
                                      iKeyYPos[(iIdx1 * 16) + iIdx2] + 8, 4,
                                      0);
                    }

                    //
                    // Clear this key from the pressed key array.
                    //
                    cPressed[(iIdx1 * 16) + iIdx2] = 0;
                }
            }
        }
    }

    //
    // Turn off the LCD panel.
    //
    LCDBacklightOff();
    LCDOff();
}
