Sonder Design Team / Mbed 2 deprecated BlackBoard_Firmware_Fast_read_not_test

Dependencies:   Memory25L16_fast USBDevice mbed

Fork of BlackBoard_Firmware_MVP by Sonder Design Team

BB_Basic.cpp

Committer:
Xinda
Date:
2018-07-07
Revision:
12:fbb1dd0586e1
Parent:
10:1f96f0cce2a0
Child:
13:f7445faded6a

File content as of revision 12:fbb1dd0586e1:

/******************************************************************************
 * S O N D E R
 * Copyright 2016 (C) Sonder Design Pty Ltd - All Rights Reserved
 * Unauthorised copying of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 *****************************************************************************/
/*
This is the first implementation of a functional firmware. It allows the user to change the Display layout and type. Improvements for later
versions will include usb keyboard support
*/
#include "mbed.h"
#include "USBHID.h"
#include "Memory.h"
#include "VKCodes.h"

//Spi port for epd. on black board P0_21, P1_21, P1_20. on QSB P0_21,P0_22,P1_15
#define EPDSPI P0_21,P0_22,P1_20
//Spi port for memory. on black board P0_9,P0_8,P0_10, P1_20. on QSB P0_9,P0_8,P0_10
#define MEMSPI P0_9,P0_8,P0_10
#define SLOTSIZE 0x50000
#define TNF 0x02
#define TFE 0x01
#define RNE 0x04

/******************************************************************************
 * Definitiontions
 */
//Constants for black board

DigitalOut cs_mem(P0_2);        //Set up memory's Chip Select pin               BB:P0_2 QSB:P0_16           spi0
DigitalOut cs_epd(P1_23);       //Set up epd's Chip Select pin                  BB:P1_23 QSB:P0_11          spi1
DigitalOut TconEn(P0_5);        //Tcon Enable pin, open drain must invert
DigitalOut start(P0_14);
DigitalIn TCbusy(P0_4);           //Tcon busy line                              P0_4

DigitalOut trigger(P1_19);
DigitalOut myled(P0_23);

DigitalOut SRclk(P0_15);        //Shift register clk signal
DigitalOut SRlat (P1_22);       //Shift register output latch
DigitalOut SRds(P1_14);         //Shiftreg data pin

DigitalIn E(P1_13);             //Definne row row A input pin
DigitalIn D(P0_7);              //Definne row row B input pin
DigitalIn C(P1_28);             //Definne row row C input pin
DigitalIn B(P1_31);             //Definne row row D input pin
DigitalIn A(P1_29);             //Definne row row E input pin

DigitalIn modC(P0_11);          //Definne row mod C input pin                    BB:P0_11 QSB:P0_1
DigitalIn modB(P0_12);          //Definne row mod B input pin
DigitalIn modA(P0_13);          //Definne row mod A input pin

Serial pc (P0_19,P0_18);        //Setup a real serial port
Memory mem(P0_2);               //Create a new memory manager with chip select on P0_2

USBHID hid(64, 8,0x1234,0x3241); //Create a HID conection with and 64 byte input and 8 byte output report, PID0x1234 VID 3241

volatile int *PIN39IOREG = (int *)0x4004403C;
int reportLength = 64;              //The length of the report recieved

//Codes to send to the pc
int readyAndWaiting []= {2,0x25,0,0,0,0,0,0};
int busy []= {2,0x50,0,0,0,0,0,0};
int readyForComand []= {2,0x75,0,0,0,0,0,0};


int GlobalAddress = 0;              //The last adress written to plus one
int lastErasedBlock =0;             //The Adress of the last erases block
int currentName = 0;                //The position in the nameList of the curret layout
char nameList[16][5];                  //A list of all the Layouts in memory, each name is 5 bytes long

//Locations in memory were the 16 layouts can be stored
const int slots [] = {0*SLOTSIZE,1*SLOTSIZE, 2*SLOTSIZE,3*SLOTSIZE, 4*SLOTSIZE, 5*SLOTSIZE, 6*SLOTSIZE, 7*SLOTSIZE, 8*SLOTSIZE, 9*SLOTSIZE,10*SLOTSIZE,11*SLOTSIZE,12*SLOTSIZE};
bool erasedSlots[]= {true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false};

int keybuffer[10][2];   //A buffer for storing key presses (mod key plus key)

int scanCode [5][14]= { //This 2D array maps key scan codes to letter codes
    {VK_OEM_3, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, VK_OEM_MINUS, VK_OEM_PLUS, VK_BACK},
    {VK_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P},
    {KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, VK_OEM_1},
    {KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, VK_LSHIFT,VK_CONTROL,VK_LMENU},
    {VK_F1, VK_F2,VK_F3,VK_F4, VK_SPACE, VK_TAB, VK_BACK, VK_RSHIFT,VK_LWIN,VK_RMENU}
};

/******************************************************************************
 * prototype Functions
 */
short bitDouble(int);

/******************************************************************************
 * Set up Functions
 */
char check(int depth)      //Check availible memory
{
    char c;
    char *ptr = new char;
    //pc.printf("stack at %p, heap at %p\n", &c, ptr);
    //pc.printf("sh,%i,%i\n", &c, ptr);
    pc.printf("mem size = %p\n", &c-ptr);
    //if (depth <= 0) return;
    //    check(depth-1);
    free(ptr);
    return 1;
}

/**
 * Set up the memory SPI
 */
SPI setupSPI()
{
    SPI my_spi(MEMSPI);    // mosi, miso, sclk
    //cs_mem = 1;                         // Chip must be deselected
    my_spi.format(8,3);             // Setup the spi for 8 bit data, low steady state clock,
    my_spi.frequency(10000000);      // second edge capture, with a 1MHz clock rate, Will work up to 20MHz
    return my_spi;
}

/*** My method to mywrite to RAM ***/
void mywrite (unsigned char data) {
    // First don't mywrite to the FIFO buffer if it is full
    while (!(LPC_SSP0->SR & TNF))       // While TNF-Bit = 0 (FIFO full)... 
        ;                               // Wait
    LPC_SSP0->DR = data;                // mywrite to FIFO buffer
}
/**
 * Setup USB HID, usefull for later not used in this iterarion
 */
/*USBHID setupUSB()
{
    USBHID hid(64, 8,0x1234,0x3241); //Create a HID conection with and 64 byte input and 8 byte output report, PID0x1234 VID 3241
    return hid;
}*/


/******************************************************************************
 * USB Functions
 */

/**
 * checks the usb recive buffer, if it contains data it is coppired to USBDataBuffer and returns 1
 * if the empty return -1;
 */
int readUSB(int USBDataBuffer[])
{
    HID_REPORT recv_report;
    if(hid.readNB(&recv_report)) {                      //Check if there is a received report
        //printf("\n");
        for(int i = 0; i<recv_report.length; i++) {     //Store the report in a locat array
            //printf(" %x", recv_report.data[i]);
            USBDataBuffer[i] = recv_report.data[i];
        }
        return 1;
    } else {
        return -1;
    }
}


/**
 * usbSend, send an eight byte report over usb
 */
void sendUSB(int usbReport[])
{
    //pc.printf("\nS: %x",usbReport[1]);
    HID_REPORT send_report;
    send_report.length = 8;

    send_report.data[0] = usbReport[0];
    send_report.data[1] = usbReport[1]; //comand byte
    send_report.data[2] = usbReport[2];
    send_report.data[3] = usbReport[3];
    send_report.data[4] = usbReport[4];
    send_report.data[5] = usbReport[5];
    send_report.data[6] = usbReport[6];
    send_report.data[7] = usbReport[7];
    hid.send(&send_report);
}




/******************************************************************************
 * Keyboard  Functions
 */

/**
 * keyScan(int keyBuffer[][]). Sacns the keyboard matrix and stores any keypresses in the 2D keyBuffer
 * If a key press was detected it returns the most recent key press, otherwise it returns 0
 */
int keyScan()
{
    //Initialise and set Up code
    int counter=0;      //Keubuffer index counter
    int rowNum = 0;
    int code =0;        //the return value, the last key pushed

    /*Clear the keybuffer*/
    for(int i = 0; i<10; i++) {
        keybuffer[i][0]=0;
        keybuffer[i][1]=0;
    }

    int noCols = 16;  //number of bits to be shifted
    int t = 1000;  //wait time in uS. This is the period in us of the shift register clock
    SRclk=0;
    SRlat = 0;
    SRds =1;    //Set first bit high


    for (int col = 0; col<noCols; col++) {    //Loop through one shifit reg
        SRclk = 1;      //clock in current bit      //        __       __
        wait_us(t/2);                               //SRclk__|  |_..._|  |_
        SRds = 0;       //set dext bit low          //      ___
        wait_us(t/2);                               //SRds |   |___..._____
        SRclk=0;                                    //          _         _
        SRlat = 1;      //latch all data out        //SRlat____| |_...___| |_
        wait_us(t/2);                               //
        SRlat=0;

        /*
        Check if a button has been pressed by scaning the rows
        Generates a unique code depending on which button has been pressed
        The code is looked up in the scanCode Array
        */
        if(A>0) {
            //pc.printf("A\n");
            rowNum = 0;
            code = scanCode[rowNum][col];
            keybuffer[counter][1]= code;
            counter++;
        }
        if(B>0) {
            //pc.printf("B\n");
            rowNum = 1;
            code = scanCode[rowNum][col];
            keybuffer[counter][1]= code;
            counter++;
        }
        if(C>0) {
            //pc.printf("C\n");
            rowNum = 2;
            code = scanCode[rowNum][col];
            keybuffer[counter][1]= code;
            counter++;
        }
        if(D>0) {
            //pc.printf("D\n");
            rowNum = 3;
            code = scanCode[rowNum][col];
            keybuffer[counter][1]= code;
            counter++;
        }
        if(E>0) {
            //pc.printf("E\n");
            rowNum = 4;
            code = scanCode[rowNum][col];
            keybuffer[counter][1]= code;
            counter++;
        }

        /*Scan the mod keys and assign them to the mod column of key buffer in the from zero up*/
        if(col>0) {
            counter=0;

            if(modC>0) {
                rowNum = 0;
                code = scanCode[rowNum][col];
                keybuffer[counter][0]= code;
            }
            if(modB>0) {
                rowNum = 0;
                code = scanCode[rowNum][col];
                keybuffer[counter][0]= code;
            }
            if(modA>0) {
                rowNum = 0;
                code = scanCode[rowNum][col];
                keybuffer[counter][0]= code;
            }
        }
    }
    return code;
}


/**
 * int sendKey(int mod, int key). Sends a keypress to the pc over usb
 */
void sendKey(int mod, int key)
{
    int temp[]= {0x01,mod,key,0,0,0,0,0};
    sendUSB(temp);
}

/**
 * int sendKey(int mod, int key). Sends a keypress to the pc over usb
 */
void sendKeyXinda(int keylocation1, int keylocation2, int keylocation3, int keylocation4, int keylocation5, int keylocation6, int keylocation7)
{
    int temp[]= {0x01,keylocation1,keylocation2,keylocation3,keylocation4,keylocation5,keylocation6,keylocation7};
    sendUSB(temp);
}

/**
 * keyCheck(), scanss the keys and sends the keypress to the pc over usb
 */
void keyCheck()
{
    //pc.printf("KeyCheck\n");
    if (keyScan()>0) {                  //check if keyScan returned key presss
        //pc.printf("\nKey scan|n");
        int countpos =0;
        while(keybuffer[countpos][1]>0) {   //While there are keypresses in the buffer
            pc.printf("%i",keybuffer[countpos][1]);
            pc.printf(" ");
            sendKey(keybuffer[countpos][0],keybuffer[countpos][1]);//Send key press
            countpos++;
            myled=0;
        }
    }
}

/**
 * testKey(), a test function from Xinda for debugging the connection between Newreadjson and BB_Basic according to the setting from CtrlCenter
 */
void testKey()
{
    pc.printf("\ntestKey function simulate keyboard event, starts in 2 sec(s)\n");
    wait_ms(1000); //give user some time to move the cursor to where they want to type
    pc.printf("\ntestKey function simulate keyboard event, starts in 1 sec(s)\n");
    wait_ms(1000);
    pc.printf("\ntestKey function start! typing...\n");
    sendKeyXinda(0,80,80,80,80,80,80); // Input Chinese: Francisco is Sonder's mascot
    wait_ms(10);
    sendKeyXinda(1,80,80,80,80,80,80); // Ctrl+V according to the Ctrl Center setting
    wait_ms(10);
    sendKeyXinda(2,80,80,80,80,80,80); // Open Google Chrome in local
    wait_ms(10);
    sendKeyXinda(0,1,80,80,80,80,80);  // Chinese lyric, <Above the Moon> or korean, depends on the layout(cmd.exe or Google chrome)
    pc.printf("\ntestKey function end!\n");
}

/******************************************************************************
 * Memory control funtions
 */


/**
 * Writes the contense of USBDataBuffer to memoryBuffer, starting at bufferIndex
 * returns the index of the last written byte+1;
 */
int appendBuffer(int USBDataBuffer[], char memoryBuffer[], int bufferIndex)
{
    //printf("\n");
    int posIndex=0;
    for(int i = 0; i < 64; i++) {

        memoryBuffer[bufferIndex+i]=USBDataBuffer[i];
        posIndex++;
    }
    return (bufferIndex+posIndex);
}

/**
 *Sends the ready and waiting signall and loops untill data is recieved.
 *Recieved data is stored in the USBDataBuffer
 */
void waitForData(int USBDataBuffer[])
{
    sendUSB(readyAndWaiting);
    while (readUSB(USBDataBuffer)<1) {
        sendUSB(readyAndWaiting);
    }
}

/**
 * Reads 'length' elements into a short array starting at the 24bit Address.
 *If length is greater than BufferSize (3840 bytes) the function will terminate
 *and return the start address. tyhe eighteight bit data read from memory is 
 doubled to sixteen bits for the display. eg 0b1010 =>0b11001100
 */
int readData(short value [], int Address, int length, int doubleSelect)
{
    //if(length>bufferSize) {
    //printf("\nLength %i exceeds Max Length\n",length);
    //return Address;
    //}
    int temp = 0;
    short temp1 = 0;
    cs_mem = 1;             //Ensure cs is deselected
    //wait_us(10);
    cs_mem = 0;                     //memory is selected
    mywrite(0x03);         //Send read command
    mywrite(Address>>16);  //Send high address byte
    mywrite(Address>>8);   //Send mid address byte
    mywrite(Address);      //Send low address byte


    for(int i =0; i <length; i++) {
        mywrite(dummy);//Send dummy byte to read out value ate Address
        while (LPC_SSP0->SR & RNE)
            temp = LPC_SSP0->DR;
        //pc.printf("Temp: %X, ", temp);
        temp1 = bitDouble(temp);
        value[i]= temp1;
        //printf(" %X",value[i]);
        Address++;
    }
    cs_mem = 1;
    return Address;     //Return the address of the next unread byte
}


/**
 * receives 64 packets over usb and stores them in memooryBuffer. When memory Buffer is full it is
 * written to memory at address. This is repeated 336 times to write a whole image to memory.
 * returns the next availible adsress;
 */
int writeImage(SPI my_spi,int Address)
{
    Timer t;
    t.start();          //Start the timer
    pc.printf("\nAddress: %i\n", Address);
    int USBDataBuffer [64];             //Creat a buffer for recived data
    char memoryBuffer [bufferSize];     //Create a memory buffer, to be sent to flash
    int bufferIndex = 0;                //points to the next available possition in memory
    int startAddress = Address;
    int imageSize = 310200;              //The number of bytes to write,  86272 for 9.8"
    while (Address<startAddress+imageSize) {
        //waitForData(USBDataBuffer);         //Waits untill data is recieved on usb, puts it in USBDataBuffer
        while(bufferIndex<bufferSize) {
            waitForData(USBDataBuffer);
            bufferIndex=appendBuffer(USBDataBuffer, memoryBuffer, bufferIndex);     //Appends USBDataBuffer onto memoryBuffer
        }
        bufferIndex=0;
        //Checks if the block has been erased. only virgin bytes can be written to, so if a block has not been errased it is write
        //protected. this erases a block before writung to it if nessisary.
        int currentSlot = Address/SLOTSIZE;
        if (erasedSlots[currentSlot]) {
            Address = mem.writeData(memoryBuffer, Address, bufferSize);
        } else {
            pc.printf("\nCan not write to unerased slot. %X", Address);
            Address = mem.writeData(memoryBuffer, Address, bufferSize);
        }

    }
    pc.printf("\n pinnished writing");
    t.stop();
    pc.printf("\nwrite image %i", t.read_ms());
    t.reset();
    return Address;
}

/**
 * Writes a single memorybuffer to memory
 * receives 64 packets over usb and stores them in memooryBuffer. When memory Buffer is full it is
 * written to memory at address.
 * returns the next availible adsress;
 */
int writeFrame(SPI my_spi,int Address)
{
    int USBDataBuffer [64];             //Creat a buffer for recived data
    char memoryBuffer [bufferSize];     //Create a memory buffer, to be sent to flash
    int bufferIndex = 0;                //points to the next available possition in memory
    Timer t;
    t.start();          //Start the timer

    waitForData(USBDataBuffer);         //Waits untill data is recieved on usb, puts it in USBDataBuffer
    t.stop();

    while(bufferIndex<bufferSize) {
        bufferIndex=appendBuffer(USBDataBuffer, memoryBuffer, bufferIndex);     //Appends USBDataBuffer onto memoryBuffer
        t.start();
        waitForData(USBDataBuffer);
        t.stop();
    }

    //Checks if the block has been erased. only virgin bytes can be written to, so if a block has not been errased it is write
    //protected. this erases a block before writung to it if nessisary.
    int currentSlot = Address/SLOTSIZE;
    pc.printf("\nCurrent slot: %i", currentSlot);
    if (erasedSlots[currentSlot]) {
        pc.printf("\nNE");
        Address = mem.writeData(memoryBuffer, Address, bufferSize);
    } else {
        pc.printf("\nCan not write to unerased slot.");
    }
    //t.stop();
    pc.printf("\nWait1  Wate2-4 %i", t.read_ms());
    t.reset();
    return Address;
}


/**
 * Sends a report containing a the name of the layout stored at a given slot
 */
void getLayoutName(int slot)
{
    int temp [] = {0x31,slot,nameList[slot][0],nameList[slot][1],nameList[slot][2],nameList[slot][3],nameList[slot][4],0};
    sendUSB(temp);
    pc.printf("\nSlot %d = %c%c%c%c%c",slot, nameList[slot][0],nameList[slot][1],nameList[slot][2],nameList[slot][3],nameList[slot][4]);
}


/**
 * Sends three reports containing the list of layout names stored in memory.
 */
void getNameList()
{
    for(int slot =0; slot< 16; slot++) {
        getLayoutName(slot);
    }
}

/**
 * Sends the name of the Current layout
 */
void getCurrentLayout()
{
    getLayoutName(currentName);
}

/**
 * Writes the name of a given layout to the top memory address in its reserved block
 * name[] is a 5 bytes char array with the most significant byte at name[0]
 */
void nameBlock(char name[], int slot)
{
    //char temp[]= {name};
    pc.printf("write name");
    mem.writeData(name, slots[slot]+0x1ff00, 5);
    pc.printf("\nName Done");
}

/**
 * Reads memory to find the names of the layouts stored. puts the names into nameList
 */
void populateNameList()
{
    for(int slot=0; slot<16; slot++) {
        short name[5];
        mem.readData(name, slots[slot]+0x1FF00, 5); //Read five bytes from the end of a slot into the name array
        for( int i = 0; i<5; i++) {
            nameList[slot][i]=name[i];
        }
    }
}

/**
 * Prepares the memory for a new Layout, writes the layout's name, and erases the blocks
 */
void prepImage(int slot, char name[])
{
    pc.printf("\nSlot: %i, %i", slot, slots[slot]);
    mem.blockErase(slots[slot]);           //erase the bottom block of the slot
    mem.blockErase(slots[slot]+0x10000);   //erase the middle block of the slot
    mem.blockErase(slots[slot]+0x20000);   //erase the top block of the slot
    mem.blockErase(slots[slot]+0x30000);   //erase the top block of the slot
    mem.blockErase(slots[slot]+0x40000);   //erase the top block of the slot
    pc.printf("\nWorking");
    //nameBlock(name,  slots[slot]/*+0x1FFF9*/); //Write the name of the layout to memory
    erasedSlots[slot]=true;                        //Mark the erased slot as true
    pc.printf("\nFin Working");
    populateNameList();
    
}


/******************************************************************************
 * Display control funtions
 */

/*###### EPD Set Up ######*/
//Sets up the EPD  spi pins
SPI setupEPD()
{
    pc.printf("\nEpd setup");
    /////Setup the spi link with the EDP////
    SPI epd_spi(EPDSPI);    //SPI setup: mosi, miso, sclk
    // Setup the spi for 16 bit data, low steady state clock,
    // second edge capture, with a 5MHz clock rate
    epd_spi.format(16,0);
    epd_spi.frequency(10000000);
    return epd_spi;
}

/******************************************************************************
 * ITE driver Functions
 */

/*###### Wait for LCD ######*/
//delay until the hardware ready pin on LCD is set
void waitForLCD()
{
    myled=1;

    while(TCbusy==0) {
        wait_us(1);
    }
    myled=0;
}

/*###### Mirror the bits in a int ######*/
int reverse(int in)
{
    int out=0;
    out|=in&128;
    out|=in&64;
    out|=in&32;
    out|=in&16;
    out|=in&8;
    out|=in&4;
    out|=in&2;
    out|=in&1;
    return out;
}

/*###### Double the number of bits (up to 16)in an int eg: 1010 => 11001100 ######*/
/*short bitDouble(int in)
{
    short out=0;
    int y = 0;
    for(int i =0; i<8; i++) {
         y = 1<<i;
        if((in&y)>0) {
        out=out|(3<<(2*i));
        }
    }
    return out;
}*/

short bitDouble(int in)
{
    short out=0;
    //1
    out=out|(3*(in&1));
    //2
    out=out|((in&2)*6);
    //4
    out=out|((in&4)*12);
    //8
    out=out|((in&8)*24);
    //16
    out=out|((in&16)*48);
    //32
    out=out|((in&32)*96);
    //64
    out=out|((in&64)*192);
    //128
    out=out|((in&128)*384);

    return out;
}


/*###### Send Comands ######*/
//send a comand to the LCD
void sendComand(SPI my_spi, int comand)
{
    waitForLCD();
    cs_epd = 0;                     // Bring chip select low
    //Send write commandpreamble  0x6000
    my_spi.write(0x6000);
    //Send   command
    my_spi.write(comand);
    cs_epd = 1;
}

/*###### Send N Data ######*/
//send some 16 bit words to the LCD
//data[] is an int array containg wordsN number of words
void sendNData(SPI my_spi,int data[], int wordsN) //for ints
{
    waitForLCD();
    cs_epd = 0;                     // Bring chip select low
    //Send write data preamble  0x0000
    mywrite(0x0000);
    //Send data
    for (int i =0; i<wordsN; i++) {
        mywrite(data[i]);
        //pc.printf("%x ",data[i]);
        waitForLCD();
    }
    cs_epd = 1;                     // Bring chip select high to stop writing
}

/*###### Send N Data ######*/
//send some 16 bit words to the LCD
//data[] is an short array containg wordsN number of 16 bit words
void sendNData(short data[], int wordsN) //for shorts
{
    waitForLCD();
    cs_epd = 0;                     // Bring chip select low
    //Send write data preamble  0x0000
    mywrite(0x0000);
    //Send data
    for (int i =0; i<wordsN; i++) {
        mywrite(data[i]);
        //pc.printf("%x ",data[i]);
        waitForLCD();
    }
    cs_epd = 1;                     // Bring chip select high to stop writing
}

/////////////////////////////////////////////////Register comands


//Read one register value
// reg_Add: address of the register you want to read.
//
int* readReg(SPI my_spi, int reg_Add)
{
    int myval[3];               //Read data buffer

    cs_epd = 0;                     // Bring chip select low
    //Send write commandpreamble  0x6000
    my_spi.write(0x6000);
    //Send read reg command 0x0010
    my_spi.write(0x0010);
    cs_epd = 1;                     // Bring chip select high to stop writing

    waitForLCD();

    cs_epd = 0;                     // Bring chip select low
    //Send write data preamble  0x0000
    my_spi.write(0x0000);
    //Send register address  0x1100
    my_spi.write(reg_Add);
    cs_epd = 1;                     // Bring chip select high to stop writing

    waitForLCD();

    cs_epd=0;
    //Send read data preamble  0x0000 ?0x0010?
    my_spi.write(0x1000);//endian swap

    myval[0]=my_spi.write(00);
    myval[1]=my_spi.write(00);
    myval[2]=my_spi.write(00);

    cs_epd = 1;                     // Bring chip select high to stop writing


    pc.printf("\n\rRef:%x %x %x %x",reg_Add,myval[0],myval[1],myval[2]);
    //=====Print data=======
    return myval;
}

/*###### Write Register ######*/
//Writes to one register
//wirtes reg_data to the registor at adress reg_Add
void writeReg(SPI my_spi, int reg_Add, int reg_data)
{
    cs_epd = 0;                     // Bring chip select low
    //Send write commandpreamble  0x6000
    my_spi.write(0x6000);
    //Send write reg command 0x0011
    my_spi.write(0x0011);
    cs_epd = 1;                     // Bring chip select high to stop writing

    waitForLCD();

    cs_epd = 0;                     // Bring chip select low
    //Send write data preamble  0x0000
    my_spi.write(0x0000);
    //Send register address
    my_spi.write(reg_Add);
    cs_epd = 1;                     // Bring chip select high to stop writing

    waitForLCD();

    cs_epd = 0;                     // Bring chip select low
    //Send write data preamble  0x0000
    my_spi.write(0x0000);
    //Send register data
    my_spi.write(reg_data);
    cs_epd = 1;                     // Bring chip select high to stop writing
}

/*###### Read Status ######*/
//Reads the staus register of the LCD
//returns 20 16bit words stored in the myval array.
void readStatus(SPI my_spi, int* myval)
{
    //my_spi.format(16,0);            // Setup the spi for 16 bit data, low steady state clock,
    //my_spi.frequency(1000000);      // second edge capture, with a 5Hz clock rate
    //int myval[20];               //Read data buffer

    cs_epd = 0;                     // Bring chip select low
    pc.printf("chec ");
    waitForLCD();
    pc.printf("check1 ");
    //Send write commandpreamble  0x6000
    my_spi.write(0x6000);
    pc.printf("check2 ");
    waitForLCD();
    //Send read status comand 0x0302 Section 2.1 in programing guide
    my_spi.write(0x0302);
    cs_epd = 1;                     // Bring chip select high to stop writing

    waitForLCD();

    cs_epd=0;
    //Send read data preamble  0x0000 ?0x0010?
    my_spi.write(0x1000);//endian swap
    waitForLCD();
    //Read the result into the data buffer
    for(int i = 0; i<20; i++) {
        waitForLCD();
        mywrite(00);//Send dummy byte to read out value ate Address
        while (LPC_SSP0->SR & RNE)
            myval[i]= LPC_SSP0->DR;//Read from data register
    }
    cs_epd = 1;                     // Bring chip select high to stop writing


    //=====Print data to the terminal=======

    pc.printf("\n\rStatus: ");
    for(int i = 0; i< 20; i++) {
        pc.printf("\n\r %x", myval[i]);
    }
    int imHi = myval[3];
    imHi = imHi<<16;
    int imaddress = myval[4]|imHi;
    pc.printf("Panel(W,H) = (%d,%d)\r\nImage Buffer Address = %X\r\n",myval[1], myval[2],imaddress);

    //pc.printf("Image Buffer Address = %X\r\n",imaddress);


}

/*###### Set Image buffer adress ######*/
//sets the bottom adress where new image buffer will be written to and the display will be read from
//imBufAddress is a 16bit address
void setImBufAddress(SPI my_spi, int imBufAddress)
{
    int ImBufAdReg = 0x208;     //Image buffer maddress register
    int addL = imBufAddress&0xffff;
    writeReg(my_spi, ImBufAdReg, addL);   //Write the low side of the address
    int addH = (imBufAddress >> 16)&0xffff;
    writeReg(my_spi, ImBufAdReg+2, addH);   //Write the high side of the address
}

/*###### Burst write Memory ######*/
//Fast write comand to send data to the LCD buffer
//writeBuffer: short buffer contsaning data to write
//mem_Add: address on the TCON to save the datat to
//write_Size: size of the writeBuffer
void burst_write_Memory(SPI my_spi, short *writeBuffer, int mem_Add, int write_Size)
{
    sendComand(my_spi, 0x0014); //Send bst write

    //int params []= {mem_Add&0xFFFF,(mem_Add>>16)&0xFFFF,write_Size&0xFFFF,(write_Size>>16)&0xFFFF,}; //Split the parameters into 16bit words
    //sendNData(params, 4); //Send paramerters
    waitForLCD();
    cs_epd=0;
    mywrite(0x0000);
    waitForLCD();
    mywrite(mem_Add&0xFFFF);
    cs_epd=1;
    waitForLCD();
    cs_epd=0;
    mywrite(0x0000);
    waitForLCD();
    mywrite((mem_Add>>16)&0xFFFF);
    cs_epd=1;
    waitForLCD();
    cs_epd=0;
    mywrite(0x0000);
    waitForLCD();
    mywrite(write_Size&0xFFFF);
    cs_epd=1;
    waitForLCD();
    cs_epd=0;
    mywrite(0x0000);
    waitForLCD();
    mywrite((write_Size>>16)&0xFFFF);
    cs_epd=1;




    waitForLCD();
    cs_epd = 0;                     // Bring chip select low

    //Send write data preamble  0x0000
    mywrite(0x0000);
    //Send data
    for(int i = 0; i< 100; i++) {
        for(int h = 0; h< write_Size; h++) {
            waitForLCD();
            mywrite(writeBuffer[h]);
            pc.printf(".");
        }
    }
    sendComand(my_spi, 0x0015); //Send burst access stop comand
}

/*###### Burst Read Memory ######*/
//Fast write comand to read data from the TCON
//readBuffer: short buffer contsaning data that was read
//mem_Add: address on the TCON to read the data from
//read_Size: size of the readBuffer
void burst_read_Memory(SPI my_spi, int *readBuffer, int mem_Add, int read_Size)
{
    pc.printf("check1");
    //Send burst reag trigger comand 0x0012
    sendComand(my_spi, 0x0012);                // Bring chip select high to stop writing

    waitForLCD();
    pc.printf("Check4");

    cs_epd = 0;                     // Bring chip select low
    //Send write data preamble  0x0000
    my_spi.write(0x0000);
    //Send memory address  low side
    my_spi.write(mem_Add);
    //Send memory address  high side
    my_spi.write(mem_Add>>16);
    cs_epd = 1;


    waitForLCD();

    cs_epd = 0;                     // Bring chip select low
    //Send write data preamble  0x0000
    my_spi.write(0x0000);
    //Send memory size  low side
    my_spi.write(read_Size);
    //Send memory address  high side
    my_spi.write(read_Size>>16);
    cs_epd = 1;

    waitForLCD();

    cs_epd = 0;                     // Bring chip select low
    //Send write commandpreamble  0x6000
    my_spi.write(0x6000);
    waitForLCD();
    //Send burst read start comand 0x0013
    my_spi.write(0x0013);
    cs_epd = 1;                     // Bring chip select high to stop writing

    waitForLCD();

    cs_epd=0;
    //Send read data preamble  0x0000 ?0x0010?
    my_spi.write(0x1000);//endian swap
    waitForLCD();
    //Read the result into the data buffer
    for(int i = 0; i<read_Size; i++) {
        waitForLCD();
        readBuffer[i]=my_spi.write(00);      //send Dummy Byte to rede out data
    }
    cs_epd = 1;                     // Bring chip select high to stop writing

    sendComand(my_spi, 0x0015); //Send burst access stop comand

}

/////////////////////////////////////////////////////////image comands
//
/**
 * loads image data into the tcon
 * ediantype 0/1 xxxxxxx1
 * pixel format bits per pixel 00=2 11=8 xxxxxx01
 * rotate 0,90, 270 xxxxxx10
 * im_buffer start of the local image buffer. data to send to the display
 * imbuffer size, lenght of the buffer
 * imPosX, imPosY, the position on the display to place the image
 * height, width, the size in pixels of the image.
 */
void load_full_image(SPI my_spi, int endianType, int pixFormat, int rotate, short im_buffer[], int imbufferSize,  int imPosX, int imPosY, int width, int height)
{

    //Write image buffer address
    //setImBufAddress(0x3dbe90);   //adress from readdata() dat[2] and data[3]

    //pc.printf("\nwidth: %d\nHeight: %d", width, height);

    //Write load image  comand 0x0020
    sendComand(my_spi, 0x0020);
    int param[] = {(endianType<<8)|(pixFormat<<4)|rotate};
    sendNData(my_spi, param,1);


    //Write load image AREA comand 0x0021
    //sendComand(0x0021);
    //Send load parameters
    //int img_param[] = {(endianType<<8)|(pixFormat<<4)|rotate, imPosX, imPosY, width, height};
    //sendNData(img_param,5);

    int count =0;
    int line=0;


    //send image data one word at a time
    waitForLCD();
    //cs_epd = 0;                     // Bring chip select low

    //Send write data preamble  0x0000
    //mywrite(0x0000);
    //Send data
    sendNData(im_buffer, imbufferSize);

    cs_epd=1;
    //pc.printf("\ncheck1");
    //send load image end coand
    sendComand(my_spi, 0x0022);
}

//Display   bitmap on EPD
/**
 *  * xstart, ystart, the position on the display to place the image
 * height, width, the size in pixels of the image.
 * mode: bits per pixel 0 =2bbp, 1=3bpp, 2=4bpp, 3=5-8bpp
 */
void displayIamge(SPI my_spi, int xstart, int ystart, int height, int width, int mode)
{
    waitForLCD();
    //Write display image comand 0x0034
    sendComand(my_spi, 0x0034);
    //Send parameters
    //t.attach_us(&ledon,5000);

    int params[] = {xstart, ystart, width, height, mode};
    trigger = 1;
    sendNData(my_spi, params,5);
}

/*###### Write Line ######*/
//Write a single line To the TCON buffer
void writeLine(SPI my_spi, int lineNum, short lineBuffer[], int size)//Writes one line to the display memory.
{
    int displayAddress = lineNum*0x960+0x3DBE90;    //set the address that the line will be stored in
    //pc.printf("\n\rline: %X Line Nume: %d",  displayAddress, lineNum);
    setImBufAddress(my_spi, displayAddress);   //0x3DBE90 adress from readdata() dat[2] and data[3]
    load_full_image(my_spi, 0,0,0, lineBuffer, size, 0,0, size,1);
    //readReg(my_spi, 0x208); //read the image base adress
}

/*###### EPD Write ######*/
//Update the whole display with data from memory, starting at the
//address: the adress in eeprom to read from
int EPD_Write(int address)
{
    Timer t;
    pc.printf("\nAddress: %i", address);
    t.start();          //Start the timer
    //Setup the SPIs
    SPI epd_spi = setupEPD();       //Creat a new SPI object to comunicate with the EPD
    int vaule[20];
    readStatus(epd_spi, vaule);

    //Create local variables
    int lineLengh = 300;            //the length of the display in 16 bit wordswords,
    int imageLength = 1034;
    short sixtyBytes[lineLengh*2];        //Create a line buffer

    //int line = 0;               //counter to keep track of the current line
    //int frameLine = 0;          //counter to keep track of the line in the current frame


    //led=!led;

    //Begin SPI comunication
    // for old Tcon
    /*cs_epd=1;           //EPD chip deselected
    TconEn =1;          //Tcon ON set High
    wait_ms(120);       //delay 120ms
    cs_epd=0;           //Select the Tcon chip
    wait_ms(1);         //delay 1ms
    //Write Header
    epd_spi.write(0x06);
    epd_spi.write(0xa0);
    wait_ms(120);   //delay 120ms*/

    //loop throug all lines lines
    for(int j=0; j<imageLength; j++) {

        //pc.printf("\n");
        readData(sixtyBytes, address+(j*lineLengh), lineLengh,0);    //Read the line, putt them in buffer return the next address to read from. Since mem reads 8bit data, we need double line length for 16bit display

        //Halve the resolution by doubling bit length
        /*for(int i=0; i<lineLengh; i++) {
            int low = sixtyBytes[i];

            low = bitDouble(low);

            sixtyBytes[i]=(low);
        }*/


        //pc.printf("ÿup");
        writeLine(epd_spi,j,sixtyBytes,lineLengh);
        if(j%100==0) {
            keyCheck();
        }

    }
    t.stop();
    displayIamge(epd_spi,0,0,1034,2400,2);

    for(int i = 0; i<1034; i++) {
        readData(sixtyBytes, address+(i*lineLengh), lineLengh-250,0);    //Read the line, putt them in buffer return the next address to read from. Since mem reads 8bit data, we need double line length for 16bit display

        //Halve the resolution by doubling bit length
        /*for(int i=0; i<lineLengh; i++) {
            int low = sixtyBytes[i];
            low = bitDouble(low);
            sixtyBytes[i]=(low);
        }*/
        writeLine(epd_spi,i,sixtyBytes,lineLengh-250);
    }
    displayIamge(epd_spi,0,0,1034,400,2);


    printf("\ntime = %i ", t.read_ms());
    t.reset();
    printf("\ndone = ");
    return 1;
}

/*###### EPD Write ######*/
//Update the whole display with data from a reserved slot
int EPD_Swap(int slot)
{
    pc.printf("\nslots: %i, %X", slot,slots[slot]);  
    return EPD_Write(slots[slot]);
}
/*******************************************************
 * Main Function
 */
int main()
{
    Timer t;


    pc.baud(115200);
    int USBDataBuffer[64];
    SPI mem_spi = setupSPI();        //Creates an SPI object to comunicate with the external memory
    populateNameList();       //Reads the names  of layouts stored in external memory into RAM

    while(1) {
        //pc.printf("Loop");
        trigger=0;

        sendUSB(readyForComand);    //Tell pc that read for data
        keyCheck();                 //Scan the key matrix for key press and send to the pc
        pc.printf(".");
        sendUSB(readyForComand);
        if (readUSB(USBDataBuffer)>0) {             //If a coamd received
            pc.printf("\nSwitch %i",USBDataBuffer[1]);
            char temp[] = {USBDataBuffer[3],USBDataBuffer[4],USBDataBuffer[5],USBDataBuffer[6],USBDataBuffer[7]};
            switch(USBDataBuffer[1]) {
                case 0x10:          //If the recieved data is a write instruction
                    GlobalAddress = writeFrame(mem_spi, USBDataBuffer[2]*65536+USBDataBuffer[3]*256+USBDataBuffer[4]);       //Write the following data to the memory at 24 bit address usbDatabuffer[2-4]
                    break;
                case 0x11:
                    pc.printf("\nPrep write");
                    prepImage(USBDataBuffer[2], temp);//Prepare a slot in memory for an image
                    break;
                case 0x12:
                    pc.printf("\nImage write");
                    writeImage(mem_spi, USBDataBuffer[2]*65536+USBDataBuffer[3]*256+USBDataBuffer[4]);//Write the next 86400 bytes of data to the memory starting at 24 bit address usbDatabuffer[2-4]
                    break;
                case 0x20:          //If the recieved comand is a read instruction
                    //mem.readData(mem_spi, memoryBuffer, USBDataBuffer[2], USBDataBuffer[3]);//read(spi, destination[], address, length)
                    //pc.printf(" \n---EPD UPDATE--- %i",USBDataBuffer[2]*65536+USBDataBuffer[3]*256+USBDataBuffer[4]);
                    EPD_Write(USBDataBuffer[2]*65536+USBDataBuffer[3]*256+USBDataBuffer[4]);
                    break;
                case 0x21:          //If the recieved comand is a swap instruction
                    EPD_Swap(USBDataBuffer[2]);
                    break;
                case 0x30:          //If the recieved comand is a request for the cutrrent name
                    populateNameList();
                    getNameList();
                    break;
                case 0x35:          //If the recieved comand is a request for all the names
                    getCurrentLayout();
                    break;
                case 0xF0:
                    testKey();  // If received command is a request of keypress debugging. Xinda Debug version of keyCheck
                    break;
                default:
                    pc.printf("\nfail! [%x %x %x %x %x %x %x %x]",USBDataBuffer[0],USBDataBuffer[1],USBDataBuffer[2],USBDataBuffer[3],USBDataBuffer[4],USBDataBuffer[5],USBDataBuffer[6],USBDataBuffer[7]);
            }
        }

        //pc.printf("\n%d", t.read_us());
        t.reset();
    }
}