first release for keyboard

Dependencies:   F401RE-USBHost2 mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // TODO: work off controler 3.3v if possible
00002 
00003 #include "mbed.h"
00004 #include "USBHostKeyboard.h"
00005 #include "stm32f4xx_flash.h"
00006 
00007 DigitalOut myled(LED1);
00008 Serial pc(USBTX, USBRX); // tx, rx
00009 DigitalInOut data(PA_8);
00010 DigitalIn button(PC_13); // eventually code to set controls
00011 
00012 extern "C" void my_wait_us_asm (int n);
00013 
00014 enum STATE {NORMAL=0, A_UP, A_DOWN, A_LEFT, A_RIGHT, DPAD_UP, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, BUTTON_START, BUTTON_B, BUTTON_A, C_UP, C_DOWN, C_LEFT, C_RIGHT, BUTTON_L, BUTTON_R, BUTTON_Z};
00015 uint8_t state = NORMAL; //done remapping when >= 19
00016 
00017 bool KeyboardButtonPressed = false;
00018 void LoadControls();
00019 void SaveControls();
00020 
00021 struct __attribute__((packed)) N64ControllerData // all bits are in the correct order
00022 {
00023     unsigned int a : 1; // 1 bit wide
00024     unsigned int b : 1;
00025     unsigned int z : 1;
00026     unsigned int start : 1;
00027     unsigned int up : 1;
00028     unsigned int down : 1;
00029     unsigned int left : 1;
00030     unsigned int right : 1;
00031     
00032     unsigned int dummy1 : 1;
00033     unsigned int dummy2 : 1;
00034     unsigned int l :1 ;
00035     unsigned int r : 1;
00036     unsigned int c_up : 1;
00037     unsigned int c_down : 1;
00038     unsigned int c_left : 1;
00039     unsigned int c_right : 1;
00040     
00041     char x_axis;
00042     
00043     char y_axis;
00044 
00045 } n64_data;
00046 
00047 struct __attribute__((packed)) KeyboardControls
00048 {
00049     uint8_t KEYBOARD_a;
00050     uint8_t KEYBOARD_b;
00051     uint8_t KEYBOARD_z;
00052     uint8_t KEYBOARD_start;
00053     
00054     uint8_t KEYBOARD_d_up;
00055     uint8_t KEYBOARD_d_down;
00056     uint8_t KEYBOARD_d_left;
00057     uint8_t KEYBOARD_d_right;
00058     
00059     uint8_t KEYBOARD_l;
00060     uint8_t KEYBOARD_r;
00061     uint8_t KEYBOARD_c_up;
00062     uint8_t KEYBOARD_c_down;
00063     
00064     uint8_t KEYBOARD_c_left;
00065     uint8_t KEYBOARD_c_right;
00066     uint8_t KEYBOARD_a_up;
00067     uint8_t KEYBOARD_a_down;
00068     
00069     uint8_t KEYBOARD_a_left;
00070     uint8_t KEYBOARD_a_right;
00071     
00072     KeyboardControls()
00073     {
00074         LoadDefault();
00075     }
00076     
00077     void LoadDefault()
00078     {
00079         KEYBOARD_a =         0x0E;
00080         KEYBOARD_b =         0x0D;
00081         KEYBOARD_z =         0x0F;
00082         KEYBOARD_start =     0x0B;
00083         KEYBOARD_d_up =      0x1D;
00084         KEYBOARD_d_down =    0x1B;
00085         KEYBOARD_d_left =    0x06;
00086         KEYBOARD_d_right =   0x19;
00087         KEYBOARD_l =         0x1A;
00088         KEYBOARD_r =         0x12;
00089         KEYBOARD_c_up =      0x17;
00090         KEYBOARD_c_down =    0x1C;
00091         KEYBOARD_c_left =    0x18;
00092         KEYBOARD_c_right =   0x0C;
00093         KEYBOARD_a_up =      0x08;
00094         KEYBOARD_a_down =    0x07;
00095         KEYBOARD_a_left =    0x16;
00096         KEYBOARD_a_right =   0x09;
00097     }
00098     
00099     void LoadBlank()
00100     {
00101         KEYBOARD_a =         0x00;
00102         KEYBOARD_b =         0x00;
00103         KEYBOARD_z =         0x00;
00104         KEYBOARD_start =     0x00;
00105         KEYBOARD_d_up =      0x00;
00106         KEYBOARD_d_down =    0x00;
00107         KEYBOARD_d_left =    0x00;
00108         KEYBOARD_d_right =   0x00;
00109         KEYBOARD_l =         0x00;
00110         KEYBOARD_r =         0x00;
00111         KEYBOARD_c_up =      0x00;
00112         KEYBOARD_c_down =    0x00;
00113         KEYBOARD_c_left =    0x00;
00114         KEYBOARD_c_right =   0x00;
00115         KEYBOARD_a_up =      0x00;
00116         KEYBOARD_a_down =    0x00;
00117         KEYBOARD_a_left =    0x00;
00118         KEYBOARD_a_right =   0x00;
00119     }
00120 };
00121 
00122 KeyboardControls kc;
00123 
00124 const int SAVE_ADDR = 0x0800C000; // sector 3
00125 KeyboardControls* saveData = (KeyboardControls*)SAVE_ADDR; 
00126 
00127 // 0 is 3 microseconds low followed by 1 microsecond high
00128 // 1 is 1 microsecond low followed by 3 microseconds high
00129 unsigned int GetMiddleOfPulse()
00130 {
00131     // wait for line to go high
00132     while(1)
00133     {
00134         if(data.read() == 1) break;
00135     }
00136     
00137     // wait for line to go low
00138     while(1)
00139     {
00140         if(data.read() == 0) break;
00141     }
00142     
00143     // now we have the falling edge
00144     // wait 2 microseconds to be in the middle of the pulse, and read. high --> 1.  low --> 0. 
00145     my_wait_us_asm(2);
00146     return (unsigned int) data.read();
00147 }
00148 
00149 // continuously read bits until at least 9 are read, confirm valid command, return without stop bit
00150 unsigned int readCommand()
00151 {
00152     unsigned int command = GetMiddleOfPulse(), bits_read = 1;
00153     
00154     while(1) // read at least 9 bits (2 bytes + stop bit)
00155     {
00156         //my_wait_us_asm(4);
00157         command = command << 1; // make room for the new bit
00158         //command += data.read(); // place the new bit into the command
00159         command += GetMiddleOfPulse();
00160         command &= 0x1FF; // remove all except the last 9 bits
00161         
00162         bits_read++;
00163         
00164         if(bits_read >= 9) // only consider when at least a whole command's length has been read
00165         {
00166             if(command == 0x3 || command == 0x1 || command == 0x1FF || command == 0x5 || command == 0x7)
00167             {
00168                 // 0x3 = 0x1 + stop bit --> get controller state
00169                 // 0x1 = 0x0 + stop bit --> who are you?
00170                 // 0x1FF = 0xFF + stop bit --> reset signal
00171                 // 0x5 = 0x10 + stop bit --> read
00172                 // 0x7 = 0x11 + stop bit --> write
00173                 command = command >> 1; // get rid of the stop bit
00174                 return command;
00175             }
00176         }
00177     }
00178 }
00179 
00180 void write_1()
00181 {
00182     data = 0;
00183     my_wait_us_asm(1);
00184     data = 1;
00185     my_wait_us_asm(3);
00186     //pc.printf("1");
00187 }
00188 
00189 void write_0()
00190 {
00191     data = 0;
00192     my_wait_us_asm(3);
00193     data = 1;
00194     my_wait_us_asm(1);
00195     //pc.printf("0");
00196 }
00197 
00198 
00199 void SendStop()
00200 {
00201     data = 0;
00202     my_wait_us_asm(1);
00203     data = 1;
00204 }
00205 
00206 // send a byte from LSB to MSB (proper serialization)
00207 void SendByte(unsigned char b)
00208 {
00209     for(int i = 0;i < 8;i++) // send all 8 bits, one at a time
00210     {
00211         if((b >> i) & 1)
00212         {
00213             write_1();
00214         }
00215         else
00216         {
00217             write_0();
00218         }
00219     }
00220 }
00221 
00222 void SendIdentity()
00223 {
00224     // reply 0x05, 0x00, 0x02
00225     SendByte(0x05);
00226     SendByte(0x00);
00227     SendByte(0x02);
00228     SendStop();
00229 }
00230 
00231 void SendControllerData()
00232 {
00233     unsigned long data = *(unsigned long*)&n64_data;
00234     unsigned int size = sizeof(data) * 8; // should be 4 bytes * 8 = 32 bits
00235     
00236     for(unsigned int i = 0;i < size;i++)
00237     {
00238         if((data >> i) & 1)
00239         {
00240             write_1();
00241         }
00242         else
00243         {
00244             write_0();
00245         }
00246     }
00247     
00248     SendStop();
00249 }
00250 
00251 char reverse(char b) 
00252 {
00253    b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
00254    b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
00255    b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
00256    return b;
00257 }
00258 
00259 void ChangeButtonMapping(uint8_t bt)
00260 {
00261     // analog settings must be hardcoded, cannot change on the fly
00262     if(state == A_UP) // state = 1 --> analog up
00263     {
00264         kc.KEYBOARD_a_up = bt;
00265     }
00266     else if(state == A_DOWN) // state = 2 --> analog up
00267     {
00268         kc.KEYBOARD_a_down = bt;
00269     }
00270     else if(state == A_LEFT) // state = 3 --> analog up
00271     {
00272         kc.KEYBOARD_a_left = bt;
00273     }
00274     else if(state == A_RIGHT) // state = 4 --> analog up
00275     {
00276         kc.KEYBOARD_a_right = bt;
00277     }
00278     else if(state == DPAD_UP) // state = 5 --> dpad up
00279     {
00280         kc.KEYBOARD_d_up = bt;
00281     }
00282     else if(state == DPAD_DOWN) // state = 6 --> dpad down
00283     {
00284         kc.KEYBOARD_d_down = bt;
00285     }
00286     else if(state == DPAD_LEFT) // state = 7 --> dpad left
00287     {
00288         kc.KEYBOARD_d_left = bt;
00289     }
00290     else if(state == DPAD_RIGHT) // state = 8 --> dpad right
00291     {
00292         kc.KEYBOARD_d_right = bt;
00293     }
00294     else if(state == BUTTON_START) // state = 9 --> start
00295     {
00296         kc.KEYBOARD_start = bt;
00297     }
00298     else if(state == BUTTON_B) // state = 10 --> B
00299     {
00300         kc.KEYBOARD_b = bt;
00301     }
00302     else if(state == BUTTON_A) // state = 11 --> A
00303     {
00304         kc.KEYBOARD_a = bt;
00305     }
00306     else if(state == C_UP) // state = 12 --> c up
00307     {
00308         kc.KEYBOARD_c_up = bt;
00309     }
00310     else if(state == C_DOWN) // state = 13 --> c down
00311     {
00312         kc.KEYBOARD_c_down = bt;
00313     }
00314     else if(state == C_LEFT) // state = 14 --> c left
00315     {
00316         kc.KEYBOARD_c_left = bt;
00317     }
00318     else if(state == C_RIGHT) // state = 15 --> c right
00319     {
00320         kc.KEYBOARD_c_right = bt;
00321     }
00322     else if(state == BUTTON_L) // state = 16 --> L
00323     {
00324         kc.KEYBOARD_l = bt;
00325     }
00326     else if(state == BUTTON_R) // state = 17 --> R
00327     {
00328         kc.KEYBOARD_r = bt;
00329     }
00330     else if(state == BUTTON_Z) // state = 18 --> Z
00331     {
00332         kc.KEYBOARD_z = bt;
00333     }
00334 }
00335 
00336 void AdvanceState()
00337 {
00338     state++;
00339     if(state >= 19) // we're done mapping the controls
00340     {
00341         SaveControls(); // write directly to flash
00342         state = NORMAL; // back to normal controller operation
00343     }
00344 }
00345 
00346 void onKeyboardEvent(uint8_t rep[9])
00347 {
00348     // the buttons all become 1 if overflow, i think.  or in short, [2] == [3]    
00349     if(rep[2] == rep[3] && rep[2] == 1)
00350         return;
00351     
00352     if(state == NORMAL)
00353     {
00354         memset(&n64_data,0,4); // clear controller state
00355         
00356         // keyboard buttons are stored in cells 2 3 4 5 6 7?  cell 0 and 1 are modifiers?  cell8 is an F?    
00357         for(int index = 2;index < 8;index++)
00358         {
00359             if(rep[index] == 0) // no key to process
00360             {
00361                 continue;
00362             }        
00363             if(rep[index] == kc.KEYBOARD_a)
00364             {
00365                 n64_data.a = 1;
00366                 continue;
00367             }
00368             if(rep[index] == kc.KEYBOARD_b)
00369             {
00370                 n64_data.b = 1;
00371                 continue;
00372             }
00373             if(rep[index] == kc.KEYBOARD_z)
00374             {
00375                 n64_data.z = 1;
00376                 continue;
00377             }
00378             if(rep[index] == kc.KEYBOARD_start)
00379             {
00380                 n64_data.start = 1;
00381                 continue;
00382             }
00383             if(rep[index] == kc.KEYBOARD_d_up)
00384             {
00385                 n64_data.up = 1;
00386                 continue;
00387             }
00388             if(rep[index] == kc.KEYBOARD_d_down)
00389             {
00390                 n64_data.down = 1;
00391                 continue;
00392             }
00393             if(rep[index] == kc.KEYBOARD_d_left)
00394             {
00395                 n64_data.left = 1;
00396                 continue;
00397             }
00398             if(rep[index] == kc.KEYBOARD_d_right)
00399             {
00400                 n64_data.right = 1;
00401                 continue;
00402             }
00403             if(rep[index] == kc.KEYBOARD_l)
00404             {
00405                 n64_data.l = 1;
00406                 continue;
00407             }
00408             if(rep[index] == kc.KEYBOARD_r)
00409             {
00410                 n64_data.r = 1;
00411                 continue;
00412             }
00413             if(rep[index] == kc.KEYBOARD_c_up)
00414             {
00415                 n64_data.c_up = 1;
00416                 continue;
00417             }
00418             if(rep[index] == kc.KEYBOARD_c_down)
00419             {
00420                 n64_data.c_down = 1;
00421                 continue;
00422             }
00423             if(rep[index] == kc.KEYBOARD_c_left)
00424             {
00425                 n64_data.c_left = 1;
00426                 continue;
00427             }
00428             if(rep[index] == kc.KEYBOARD_c_right)
00429             {
00430                 n64_data.c_right = 1;
00431                 continue;
00432             }
00433             // NOTE: THESE BITS MUST BE WRITTEN IN REVERSE ORDER.  HIGH BIT IS IN THE LOW POSITION
00434             if(rep[index] == kc.KEYBOARD_a_up)
00435             {
00436                 //n64_data.y_axis = 0x0A; // 80(dec) bit reversed
00437                 n64_data.y_axis = 0xB4; // 2D = 45 = 35% = no tap jump.  bit reverse 2D (00101101) to get B4 (10110100)
00438                 continue;
00439             }
00440             if(rep[index] == kc.KEYBOARD_a_down)
00441             {
00442                 n64_data.y_axis = 0x0D; // -80(dec) bit reversed
00443                 continue;
00444             }
00445             if(rep[index] == kc.KEYBOARD_a_left)
00446             {
00447                 n64_data.x_axis = 0x0D;
00448                 continue;
00449             }
00450             if(rep[index] == kc.KEYBOARD_a_right)
00451             {
00452                 n64_data.x_axis = 0x0A;
00453                 continue;
00454             }
00455         }
00456     }
00457     else // state > 0 so we are in the process of changing controls
00458     {
00459         uint8_t b = rep[2]; // read for button presses (just take first pressed if many are pressed)
00460         if(b != 0) /*button was actually is pressed*/
00461         {
00462             if(KeyboardButtonPressed == false)
00463             {
00464                 KeyboardButtonPressed = true;
00465                 ChangeButtonMapping(b);
00466                 AdvanceState();
00467             }
00468         }
00469         else
00470         {
00471             KeyboardButtonPressed = false;
00472         }
00473     }
00474 }
00475 
00476 void PrintBytes(char *ptr, int numBytes)
00477 {
00478     pc.printf("[");
00479     for(int i=0;i < numBytes;i++)
00480     {
00481         pc.printf(" %X ",*ptr);
00482         ptr++;
00483     }
00484     pc.printf("]\r\n");
00485 }
00486 
00487 void SaveControls()
00488 {
00489     FLASH_Unlock(); //unlock flash writing
00490     FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 
00491                   FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
00492     FLASH_EraseSector(FLASH_Sector_3,VoltageRange_3); // 0x0800C000 - 0x0800FFFF
00493     
00494     uint32_t* data = (uint32_t*)&kc;
00495     
00496     // total size is 18 bytes
00497     // Note: ProgramDoubleWord requires a higher voltage
00498     FLASH_ProgramWord(SAVE_ADDR,*data); // write word 1 (4 bytes)
00499     data++;
00500     FLASH_ProgramWord(SAVE_ADDR+0x04,*data); // write word 2 (4 bytes)
00501     data++;
00502     FLASH_ProgramWord(SAVE_ADDR+0x08,*data); // write word 3 (4 bytes)
00503     data++;
00504     FLASH_ProgramWord(SAVE_ADDR+0x0C,*data); // write word 4 (4 bytes)
00505     data++;
00506     FLASH_ProgramHalfWord(SAVE_ADDR+0x10,*data); // write final half word (2 bytes)
00507         
00508     FLASH_Lock(); // lock it back up
00509 }
00510 
00511 
00512 
00513 void LoadControls()
00514 {
00515     memcpy(&kc,saveData,sizeof(KeyboardControls));
00516     pc.printf("Controls have been loaded!\r\n");
00517 }
00518 
00519 int main()
00520 {
00521     bool buttonPressed = false;
00522     
00523     pc.printf("\r\nNow loaded! SystemCoreClock = %d Hz\r\n", SystemCoreClock);
00524     LoadControls();
00525 
00526     USBHostKeyboard kb;
00527     if (!kb.connect()) {
00528         pc.printf("Error: USB kb not found.\n");
00529     }
00530     // when connected, attach handler called on kb event
00531     kb.attach(onKeyboardEvent);
00532     
00533     while(1)
00534     {
00535         if(state == NORMAL)
00536         {
00537             if(!button) // user wants to change controls
00538             {
00539                 if(!buttonPressed) // make sure it's a separate button press
00540                 {
00541                     buttonPressed = true;
00542                     state++;
00543                     continue;
00544                 }
00545             }
00546             else
00547             {
00548                 buttonPressed = false;
00549             }
00550             
00551             // Set pin mode to input
00552             data.input();
00553             
00554             USBHost::poll();
00555             
00556             __disable_irq();    // Disable Interrupts
00557             
00558             // Read 64 command
00559             unsigned int cmd = readCommand();
00560             
00561             my_wait_us_asm(2); // wait a small amount of time before replying
00562      
00563             //-------- SEND RESPONSE
00564             // Set pin mode to output
00565             data.output();
00566             
00567             switch(cmd)
00568             {
00569                 case 0x00: // identity
00570                 case 0xFF: // reset
00571                     SendIdentity();
00572                     break;
00573                 case 0x01: // poll for state
00574                     SendControllerData();
00575                     break;
00576                 default:
00577                     // we do not process the read and write commands (memory pack)
00578                     break;
00579             }
00580             __enable_irq();    // Enable Interrupts
00581             //-------- DONE SENDING RESPOSE
00582         }
00583         else
00584         {
00585             if(!button) // user wants to cancel and return to regular mode
00586             {
00587                 if(!buttonPressed) // make sure it's a separate button press
00588                 {
00589                     state = NORMAL;
00590                     buttonPressed = true;
00591                     continue;
00592                 }
00593             }
00594             else
00595             {
00596                 buttonPressed = false;
00597             }
00598             
00599             myled = !myled;
00600             USBHost::poll();
00601             wait(0.1);
00602             
00603             if(state == NORMAL) // about to return to normal operation, make sure the LED remains off
00604             {
00605                 myled = false;
00606                 KeyboardButtonPressed = false;
00607             }
00608         }
00609     }
00610 }