Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Memory25L16_fast USBDevice mbed
Fork of BlackBoard_Firmware_MVP by
BB_Basic.cpp
- Committer:
- ThomasSonderDesign
- Date:
- 2016-12-22
- Revision:
- 5:07113abf18c0
- Parent:
- 4:e6e1642724d4
- Child:
- 6:2f4a272ab299
File content as of revision 5:07113abf18c0:
/****************************************************************************** * 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" /****************************************************************************** * Definitiontions */ //Constants for black board DigitalOut cs_mem(P0_2); //Set up memory's Chip Select pin DigitalOut cs_epd(P1_23); //Set up epd's Chip Select pin DigitalOut TconEn(P0_5); //Tcon Enable pin, open drain must invert DigitalOut start(P0_14); DigitalOut myled(P0_9); 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 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,0x20000, 0x40000,0x60000, 0x80000, 0xa0000, 0xc0000, 0xe0000, 0x100000, 0x120000,0x140000,0x160000,0x180000, 0x1a0000,0x1e0000}; bool erasedSlots[]= {true,false,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} }; /****************************************************************************** * 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(P0_9,P0_8,P0_10); // 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(1000000); // second edge capture, with a 1MHz clock rate, Will work up to 20MHz return my_spi; } /** * 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); } /****************************************************************************** * 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); } } /** * 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; while (Address<startAddress+86272) { //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/0x20000; if (erasedSlots[currentSlot]) { Address = mem.writeData(my_spi, memoryBuffer, Address, bufferSize); } else { pc.printf("\nCan not write to unerased slot."); Address = mem.writeData(my_spi, 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/0x20000; pc.printf("\nCurrent slot: %i", currentSlot); if (erasedSlots[currentSlot]) { pc.printf("\nNE"); Address = mem.writeData(my_spi, 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); } /** * 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(SPI my_spi, char name[], int slot) { //char temp[]= {name}; mem.writeData(my_spi, name, slots[slot]+0x1fff9, 5); } /** * Reads memory to find the names of the layouts stored. puts the names into nameList */ void populateNameList(SPI my_spi) { for(int slot=0; slot<16; slot++) { char name[5]; mem.readData(my_spi, name, slots[slot]+0x1FFF9, 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(SPI my_spi, int slot, char name[]) { pc.printf("\nSlot: %i", slots[slot]); mem.blockErase(my_spi, slots[slot]); //erase the bottom block of the slot mem.blockErase(my_spi, slots[slot]+0x10000); //erase the top block of the slot //nameBlock(my_spi, name, slots[slot]+0x1FFF9); //Write the name of the layout to memory erasedSlots[slot]=true; //Mark the erased slot as true } /****************************************************************************** * 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(P0_21, P1_21, P1_20); //SPI setup: mosi, miso, sclk // Setup the spi for 8 bit data, high steady state clock, // second edge capture, with a 5MHz clock rate epd_spi.format(8,3); epd_spi.frequency(5000000); return epd_spi; } /*###### EPD Write ######*/ //Update the whole display with data from memory, starting at the int EPD_Write(SPI mem_spi, int address) { pc.printf("\nAddress: %i", address); //Setup the SPIs SPI epd_spi = setupEPD(); //Creat a new SPI object to comunicate with the EPD //Create local variables int lineLengh = 60; //the length of the display in bytes char sixtyBytes[lineLengh]; //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; //Timer t; //t.start(); //Start the timer //Begin SPI comunication 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 1440 lines for(int j=0; j<1440; j++) { //pc.printf("\n"); mem.readData(mem_spi, sixtyBytes, address, lineLengh); //Read the line, putt them in buffer return the next address to read from for(int i =0; i<lineLengh; i++) { //Read one byte from the buffer epd_spi.write(sixtyBytes[i]); //and write it to the display //pc.printf("%i%i%i%i%i%i%i%i",sixtyBytes[i]>>7&&1,sixtyBytes[i]>>6&&1,sixtyBytes[i]>>5&&1,sixtyBytes[i]>>4&&1,sixtyBytes[i]>>3&&1,sixtyBytes[i]>>2&&1,sixtyBytes[i]>>1&&1,sixtyBytes[i]&&1); address++; //byteCounter++; } epd_spi.write(00); //Write a 0 at the end of each line //wait_us(10000); } wait_us(1000); DigitalOut sclk(P0_13); //serial clk sclk = 0; cs_epd=1; //Deselct the chip //t.stop(); wait(10); //Wait 5s for the EPD to update TconEn=0; //Deassert Tcon ON cs_epd=0; //Deassert chip select //printf("\ntime = %i ", t.read_ms()); //t.reset(); return 1; } /*###### EPD Write ######*/ //Update the whole display with data from a reserved slot int EPD_Swap(SPI mem_spi, int slot) { return EPD_Write(mem_spi, slots[slot]); } /******************************************************* * Main Function */ int main() { Timer t; int USBDataBuffer[64]; SPI my_spi = setupSPI(); //Creates an SPI object to comunicate with the external memory populateNameList(my_spi); //Reads the names of layouts stored in external memory into RAM while(1) { pc.printf("Loop"); sendUSB(readyForComand); 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; } } sendUSB(readyForComand); if (readUSB(USBDataBuffer)>0) { 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(my_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(my_spi, USBDataBuffer[2], temp);//Prepare a slot in memory for an image break; case 0x12: pc.printf("\nImage write"); writeImage(my_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(my_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(my_spi, USBDataBuffer[2]*65536+USBDataBuffer[3]*256+USBDataBuffer[4]); break; case 0x30: //If the recieved comand is a request for the cutrrent name getCurrentLayout(); break; case 0x35: //If the recieved comand is a request for all the names getCurrentLayout(); 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(); } }