v1 Stable

Dependencies:   F401RE-USBHost USBHostXpad mbed

Revision:
1:3c21da72660d
Parent:
0:eb2258e8c4b5
Child:
2:c20d8438f206
--- a/main.cpp	Wed Oct 26 02:02:09 2016 +0000
+++ b/main.cpp	Mon Oct 31 19:26:40 2016 +0000
@@ -1,11 +1,61 @@
+//TODO: save controller layout to sram
+// finish and make 100% functional for keyboard players
+// duplicate program and modify to work with x360
+
 #include "mbed.h"
+#include "USBHostKeyboard.h"
 
 extern "C" void my_wait_us_asm (int n);
 
+struct __attribute__((packed)) N64ControllerData // all bits are in the correct order
+{
+    unsigned int a : 1; // 1 bit wide
+    unsigned int b : 1;
+    unsigned int z : 1;
+    unsigned int start : 1;
+    unsigned int up : 1;
+    unsigned int down : 1;
+    unsigned int left : 1;
+    unsigned int right : 1;
+    
+    unsigned int dummy1 : 1;
+    unsigned int dummy2 : 1;
+    unsigned int l :1 ;
+    unsigned int r : 1;
+    unsigned int c_up : 1;
+    unsigned int c_down : 1;
+    unsigned int c_left : 1;
+    unsigned int c_right : 1;
+    
+    char x_axis;
+    
+    char y_axis;
+
+} n64_data;
+
+const uint8_t KEYBOARD_a =         0x0E;
+const uint8_t KEYBOARD_b =         0x0D;
+const uint8_t KEYBOARD_z =         0x0F;
+const uint8_t KEYBOARD_start =     0x0B;
+const uint8_t KEYBOARD_d_up =      0x1D;
+const uint8_t KEYBOARD_d_down =    0x1B;
+const uint8_t KEYBOARD_d_left =    0x06;
+const uint8_t KEYBOARD_d_right =   0x19;
+const uint8_t KEYBOARD_l =         0x1A;
+const uint8_t KEYBOARD_r =         0x12;
+const uint8_t KEYBOARD_c_up =      0x17;
+const uint8_t KEYBOARD_c_down =    0x1C;
+const uint8_t KEYBOARD_c_left =    0x18;
+const uint8_t KEYBOARD_c_right =   0x0C; 
+const uint8_t KEYBOARD_a_up =      0x08;
+const uint8_t KEYBOARD_a_down =    0x07;
+const uint8_t KEYBOARD_a_left =    0x16;
+const uint8_t KEYBOARD_a_right =   0x09;
+
 DigitalOut myled(LED1);
 Serial pc(USBTX, USBRX); // tx, rx
 DigitalInOut data(PA_8);
-DigitalIn button(PC_13);
+//DigitalIn button(PC_13); // eventually code to set controlls
 
 // 0 is 3 microseconds low followed by 1 microsecond high
 // 1 is 1 microsecond low followed by 3 microseconds high
@@ -46,11 +96,13 @@
         
         if(bits_read >= 9) // only consider when at least a whole command's length has been read
         {
-            if(command == 0x3 || command == 0x1 || command == 0x1FF)
+            if(command == 0x3 || command == 0x1 || command == 0x1FF || command == 0x5 || command == 0x7)
             {
                 // 0x3 = 0x1 + stop bit --> get controller state
                 // 0x1 = 0x0 + stop bit --> who are you?
                 // 0x1FF = 0xFF + stop bit --> reset signal
+                // 0x5 = 0x10 + stop bit --> read
+                // 0x7 = 0x11 + stop bit --> write
                 command = command >> 1; // get rid of the stop bit
                 return command;
             }
@@ -64,7 +116,6 @@
     my_wait_us_asm(1);
     data = 1;
     my_wait_us_asm(3);
-    //data = 0;
     //pc.printf("1");
 }
 
@@ -74,23 +125,21 @@
     my_wait_us_asm(3);
     data = 1;
     my_wait_us_asm(1);
-    //data = 0;
     //pc.printf("0");
 }
 
 
-void sendStop()
+void SendStop()
 {
     data = 0;
     my_wait_us_asm(1);
     data = 1;
 }
 
-void sendByte(unsigned char b)
+// send a byte from LSB to MSB (proper serialization)
+void SendByte(unsigned char b)
 {
-    //pc.printf("\nTrying to send 0x%x\n",b);
     for(int i = 0;i < 8;i++) // send all 8 bits, one at a time
-    //for(int i = 7;i >= 0;i--) // send all 8 bits, in reverse order, one at a time
     {
         if((b >> i) & 1)
         {
@@ -103,23 +152,145 @@
     }
 }
 
+void SendIdentity()
+{
+    // reply 0x05, 0x00, 0x02
+    SendByte(0x05);
+    SendByte(0x00);
+    SendByte(0x02);
+    SendStop();
+}
+
+void SendControllerData()
+{
+    unsigned long data = *(unsigned long*)&n64_data;
+    unsigned int size = sizeof(data) * 8; // should be 4 bytes * 8 = 32 bits
+    
+    for(unsigned int i = 0;i < size;i++)
+    {
+        if((data >> i) & 1)
+        {
+            write_1();
+        }
+        else
+        {
+            write_0();
+        }
+    }
+    
+    SendStop();
+}
+
+// keyboard buttons are stored in cells 2 3 4 5 6 7?  cell 0 and 1 are modifiers?  cell8 is an F?
+// the buttons all become 1 if overflow, i think.  or in short, [2] == [3]
+void onKeyboardEvent(uint8_t rep[9])
+{
+    /*printf("Report = [");
+    for(int i = 0;i < 8;i++)
+    {
+        printf("%X, ", rep[i]);
+    }
+    printf("%X]\r\n", rep[8]);*/
+    
+    memset(&n64_data,0,4); // clear controller state
+    
+    bool leaveLoop = false;
+    
+    for(int index = 2;index < 8;index++)
+    {
+        switch(rep[index]) // the key code
+        {
+            case 0: // no more keys to process
+                leaveLoop = true;
+                break;
+            case KEYBOARD_a:
+                n64_data.a = 1;
+                break;
+            case KEYBOARD_b:
+                n64_data.b = 1;
+                break;
+            case KEYBOARD_z:
+                n64_data.z = 1;
+                break;
+            case KEYBOARD_start:
+                n64_data.start = 1;
+                break;
+            case KEYBOARD_d_up:
+                n64_data.up = 1;
+                break;
+            case KEYBOARD_d_down:
+                n64_data.down = 1;
+                break;
+            case KEYBOARD_d_left:
+                n64_data.left = 1;
+                break;
+            case KEYBOARD_d_right:
+                n64_data.right = 1;
+                break;
+            case KEYBOARD_l:
+                n64_data.l = 1;
+                break;
+            case KEYBOARD_r:
+                n64_data.r = 1;
+                break;
+            case KEYBOARD_c_up:
+                n64_data.c_up = 1;
+                break;
+            case KEYBOARD_c_down:
+                n64_data.c_down = 1;
+                break;
+            case KEYBOARD_c_left:
+                n64_data.c_left = 1;
+                break;
+            case KEYBOARD_c_right:
+                n64_data.c_right = 1;
+                break;
+            // NOTE: THESE BITS MUST BE WRITTEN IN REVERSE ORDER.  HIGH BIT IS IN THE LOW POSITION
+            case KEYBOARD_a_up:
+                n64_data.y_axis = 0x0A;
+                break;
+            case KEYBOARD_a_down:
+                n64_data.y_axis = 0x0D;
+                break;
+            case KEYBOARD_a_left:
+                n64_data.x_axis = 0x0D;
+                break;
+            case KEYBOARD_a_right:
+                n64_data.x_axis = 0x0A;
+                break;
+        }
+        
+        if(leaveLoop) break;
+    }
+}
+
 int main()
 {
-    __disable_irq();    // Disable Interrupts
-    pc.printf("SystemCoreClock = %d Hz\n", SystemCoreClock);
+    pc.printf("Now loaded! SystemCoreClock = %d Hz\r\n", SystemCoreClock);
+    memset(&n64_data,0,4); // start controller in the neutral state
+
+    USBHostKeyboard kb;
+    if (!kb.connect()) {
+        pc.printf("Error: USB kb not found.\n");
+    }
+    // when connected, attach handler called on kb event
+    kb.attach(onKeyboardEvent);
     
     while(1)
     {
         // Set pin mode to input
         data.input();
         
-        // Read command
+        // Read keyboard state?
+        USBHost::poll();
+        
+        __disable_irq();    // Disable Interrupts
+        // Read 64 command
         unsigned int cmd = readCommand();
         
-        //pc.printf("Read command: %u\n", cmd);
-        
         my_wait_us_asm(2); // wait a small amount of time before replying
-        
+ 
+        //-------- SEND RESPONSE
         // Set pin mode to output
         data.output();
         
@@ -127,33 +298,16 @@
         {
             case 0x00: // identity
             case 0xFF: // reset
-                //pc.printf("Received identity ");
-                // reply 0x05, 0x00, 0x02
-                sendByte(0x05);
-                sendByte(0x00);
-                sendByte(0x02);
-                sendStop();
+                SendIdentity();
                 break;
             case 0x01: // poll for state
-                if(!button.read()) // simulate Start pressed
-                {
-                    sendByte(0x08); // I think this is start, 4th bit
-                    sendByte(0x00);
-                    sendByte(0x00);
-                    sendByte(0x00);
-                    sendStop();
-                    break;
-                }
-                else
-                {
-                    // respond with controller state
-                    sendByte(0x00);
-                    sendByte(0x00);
-                    sendByte(0x00);
-                    sendByte(0x00);
-                    sendStop();
-                    break;
-                }
+                SendControllerData();
+                break;
+            default:
+                // we do not process the read and write commands (memory pack)
+                break;
         }
+        __enable_irq();    // Enable Interrupts
+        //-------- DONE SENDING RESPOSE   
     }
 }