first release for keyboard

Dependencies:   F401RE-USBHost2 mbed

Committer:
Ownasaurus
Date:
Mon Oct 31 19:26:40 2016 +0000
Revision:
1:3c21da72660d
Parent:
0:eb2258e8c4b5
Child:
2:77b20c9b1933
Functional KB<-->N64

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Ownasaurus 1:3c21da72660d 1 //TODO: save controller layout to sram
Ownasaurus 1:3c21da72660d 2 // finish and make 100% functional for keyboard players
Ownasaurus 1:3c21da72660d 3 // duplicate program and modify to work with x360
Ownasaurus 1:3c21da72660d 4
Ownasaurus 0:eb2258e8c4b5 5 #include "mbed.h"
Ownasaurus 1:3c21da72660d 6 #include "USBHostKeyboard.h"
Ownasaurus 0:eb2258e8c4b5 7
Ownasaurus 0:eb2258e8c4b5 8 extern "C" void my_wait_us_asm (int n);
Ownasaurus 0:eb2258e8c4b5 9
Ownasaurus 1:3c21da72660d 10 struct __attribute__((packed)) N64ControllerData // all bits are in the correct order
Ownasaurus 1:3c21da72660d 11 {
Ownasaurus 1:3c21da72660d 12 unsigned int a : 1; // 1 bit wide
Ownasaurus 1:3c21da72660d 13 unsigned int b : 1;
Ownasaurus 1:3c21da72660d 14 unsigned int z : 1;
Ownasaurus 1:3c21da72660d 15 unsigned int start : 1;
Ownasaurus 1:3c21da72660d 16 unsigned int up : 1;
Ownasaurus 1:3c21da72660d 17 unsigned int down : 1;
Ownasaurus 1:3c21da72660d 18 unsigned int left : 1;
Ownasaurus 1:3c21da72660d 19 unsigned int right : 1;
Ownasaurus 1:3c21da72660d 20
Ownasaurus 1:3c21da72660d 21 unsigned int dummy1 : 1;
Ownasaurus 1:3c21da72660d 22 unsigned int dummy2 : 1;
Ownasaurus 1:3c21da72660d 23 unsigned int l :1 ;
Ownasaurus 1:3c21da72660d 24 unsigned int r : 1;
Ownasaurus 1:3c21da72660d 25 unsigned int c_up : 1;
Ownasaurus 1:3c21da72660d 26 unsigned int c_down : 1;
Ownasaurus 1:3c21da72660d 27 unsigned int c_left : 1;
Ownasaurus 1:3c21da72660d 28 unsigned int c_right : 1;
Ownasaurus 1:3c21da72660d 29
Ownasaurus 1:3c21da72660d 30 char x_axis;
Ownasaurus 1:3c21da72660d 31
Ownasaurus 1:3c21da72660d 32 char y_axis;
Ownasaurus 1:3c21da72660d 33
Ownasaurus 1:3c21da72660d 34 } n64_data;
Ownasaurus 1:3c21da72660d 35
Ownasaurus 1:3c21da72660d 36 const uint8_t KEYBOARD_a = 0x0E;
Ownasaurus 1:3c21da72660d 37 const uint8_t KEYBOARD_b = 0x0D;
Ownasaurus 1:3c21da72660d 38 const uint8_t KEYBOARD_z = 0x0F;
Ownasaurus 1:3c21da72660d 39 const uint8_t KEYBOARD_start = 0x0B;
Ownasaurus 1:3c21da72660d 40 const uint8_t KEYBOARD_d_up = 0x1D;
Ownasaurus 1:3c21da72660d 41 const uint8_t KEYBOARD_d_down = 0x1B;
Ownasaurus 1:3c21da72660d 42 const uint8_t KEYBOARD_d_left = 0x06;
Ownasaurus 1:3c21da72660d 43 const uint8_t KEYBOARD_d_right = 0x19;
Ownasaurus 1:3c21da72660d 44 const uint8_t KEYBOARD_l = 0x1A;
Ownasaurus 1:3c21da72660d 45 const uint8_t KEYBOARD_r = 0x12;
Ownasaurus 1:3c21da72660d 46 const uint8_t KEYBOARD_c_up = 0x17;
Ownasaurus 1:3c21da72660d 47 const uint8_t KEYBOARD_c_down = 0x1C;
Ownasaurus 1:3c21da72660d 48 const uint8_t KEYBOARD_c_left = 0x18;
Ownasaurus 1:3c21da72660d 49 const uint8_t KEYBOARD_c_right = 0x0C;
Ownasaurus 1:3c21da72660d 50 const uint8_t KEYBOARD_a_up = 0x08;
Ownasaurus 1:3c21da72660d 51 const uint8_t KEYBOARD_a_down = 0x07;
Ownasaurus 1:3c21da72660d 52 const uint8_t KEYBOARD_a_left = 0x16;
Ownasaurus 1:3c21da72660d 53 const uint8_t KEYBOARD_a_right = 0x09;
Ownasaurus 1:3c21da72660d 54
Ownasaurus 0:eb2258e8c4b5 55 DigitalOut myled(LED1);
Ownasaurus 0:eb2258e8c4b5 56 Serial pc(USBTX, USBRX); // tx, rx
Ownasaurus 0:eb2258e8c4b5 57 DigitalInOut data(PA_8);
Ownasaurus 1:3c21da72660d 58 //DigitalIn button(PC_13); // eventually code to set controlls
Ownasaurus 0:eb2258e8c4b5 59
Ownasaurus 0:eb2258e8c4b5 60 // 0 is 3 microseconds low followed by 1 microsecond high
Ownasaurus 0:eb2258e8c4b5 61 // 1 is 1 microsecond low followed by 3 microseconds high
Ownasaurus 0:eb2258e8c4b5 62 unsigned int GetMiddleOfPulse()
Ownasaurus 0:eb2258e8c4b5 63 {
Ownasaurus 0:eb2258e8c4b5 64 // wait for line to go high
Ownasaurus 0:eb2258e8c4b5 65 while(1)
Ownasaurus 0:eb2258e8c4b5 66 {
Ownasaurus 0:eb2258e8c4b5 67 if(data.read() == 1) break;
Ownasaurus 0:eb2258e8c4b5 68 }
Ownasaurus 0:eb2258e8c4b5 69
Ownasaurus 0:eb2258e8c4b5 70 // wait for line to go low
Ownasaurus 0:eb2258e8c4b5 71 while(1)
Ownasaurus 0:eb2258e8c4b5 72 {
Ownasaurus 0:eb2258e8c4b5 73 if(data.read() == 0) break;
Ownasaurus 0:eb2258e8c4b5 74 }
Ownasaurus 0:eb2258e8c4b5 75
Ownasaurus 0:eb2258e8c4b5 76 // now we have the falling edge
Ownasaurus 0:eb2258e8c4b5 77 // wait 2 microseconds to be in the middle of the pulse, and read. high --> 1. low --> 0.
Ownasaurus 0:eb2258e8c4b5 78 my_wait_us_asm(2);
Ownasaurus 0:eb2258e8c4b5 79 return (unsigned int) data.read();
Ownasaurus 0:eb2258e8c4b5 80 }
Ownasaurus 0:eb2258e8c4b5 81
Ownasaurus 0:eb2258e8c4b5 82 // continuously read bits until at least 9 are read, confirm valid command, return without stop bit
Ownasaurus 0:eb2258e8c4b5 83 unsigned int readCommand()
Ownasaurus 0:eb2258e8c4b5 84 {
Ownasaurus 0:eb2258e8c4b5 85 unsigned int command = GetMiddleOfPulse(), bits_read = 1;
Ownasaurus 0:eb2258e8c4b5 86
Ownasaurus 0:eb2258e8c4b5 87 while(1) // read at least 9 bits (2 bytes + stop bit)
Ownasaurus 0:eb2258e8c4b5 88 {
Ownasaurus 0:eb2258e8c4b5 89 //my_wait_us_asm(4);
Ownasaurus 0:eb2258e8c4b5 90 command = command << 1; // make room for the new bit
Ownasaurus 0:eb2258e8c4b5 91 //command += data.read(); // place the new bit into the command
Ownasaurus 0:eb2258e8c4b5 92 command += GetMiddleOfPulse();
Ownasaurus 0:eb2258e8c4b5 93 command &= 0x1FF; // remove all except the last 9 bits
Ownasaurus 0:eb2258e8c4b5 94
Ownasaurus 0:eb2258e8c4b5 95 bits_read++;
Ownasaurus 0:eb2258e8c4b5 96
Ownasaurus 0:eb2258e8c4b5 97 if(bits_read >= 9) // only consider when at least a whole command's length has been read
Ownasaurus 0:eb2258e8c4b5 98 {
Ownasaurus 1:3c21da72660d 99 if(command == 0x3 || command == 0x1 || command == 0x1FF || command == 0x5 || command == 0x7)
Ownasaurus 0:eb2258e8c4b5 100 {
Ownasaurus 0:eb2258e8c4b5 101 // 0x3 = 0x1 + stop bit --> get controller state
Ownasaurus 0:eb2258e8c4b5 102 // 0x1 = 0x0 + stop bit --> who are you?
Ownasaurus 0:eb2258e8c4b5 103 // 0x1FF = 0xFF + stop bit --> reset signal
Ownasaurus 1:3c21da72660d 104 // 0x5 = 0x10 + stop bit --> read
Ownasaurus 1:3c21da72660d 105 // 0x7 = 0x11 + stop bit --> write
Ownasaurus 0:eb2258e8c4b5 106 command = command >> 1; // get rid of the stop bit
Ownasaurus 0:eb2258e8c4b5 107 return command;
Ownasaurus 0:eb2258e8c4b5 108 }
Ownasaurus 0:eb2258e8c4b5 109 }
Ownasaurus 0:eb2258e8c4b5 110 }
Ownasaurus 0:eb2258e8c4b5 111 }
Ownasaurus 0:eb2258e8c4b5 112
Ownasaurus 0:eb2258e8c4b5 113 void write_1()
Ownasaurus 0:eb2258e8c4b5 114 {
Ownasaurus 0:eb2258e8c4b5 115 data = 0;
Ownasaurus 0:eb2258e8c4b5 116 my_wait_us_asm(1);
Ownasaurus 0:eb2258e8c4b5 117 data = 1;
Ownasaurus 0:eb2258e8c4b5 118 my_wait_us_asm(3);
Ownasaurus 0:eb2258e8c4b5 119 //pc.printf("1");
Ownasaurus 0:eb2258e8c4b5 120 }
Ownasaurus 0:eb2258e8c4b5 121
Ownasaurus 0:eb2258e8c4b5 122 void write_0()
Ownasaurus 0:eb2258e8c4b5 123 {
Ownasaurus 0:eb2258e8c4b5 124 data = 0;
Ownasaurus 0:eb2258e8c4b5 125 my_wait_us_asm(3);
Ownasaurus 0:eb2258e8c4b5 126 data = 1;
Ownasaurus 0:eb2258e8c4b5 127 my_wait_us_asm(1);
Ownasaurus 0:eb2258e8c4b5 128 //pc.printf("0");
Ownasaurus 0:eb2258e8c4b5 129 }
Ownasaurus 0:eb2258e8c4b5 130
Ownasaurus 0:eb2258e8c4b5 131
Ownasaurus 1:3c21da72660d 132 void SendStop()
Ownasaurus 0:eb2258e8c4b5 133 {
Ownasaurus 0:eb2258e8c4b5 134 data = 0;
Ownasaurus 0:eb2258e8c4b5 135 my_wait_us_asm(1);
Ownasaurus 0:eb2258e8c4b5 136 data = 1;
Ownasaurus 0:eb2258e8c4b5 137 }
Ownasaurus 0:eb2258e8c4b5 138
Ownasaurus 1:3c21da72660d 139 // send a byte from LSB to MSB (proper serialization)
Ownasaurus 1:3c21da72660d 140 void SendByte(unsigned char b)
Ownasaurus 0:eb2258e8c4b5 141 {
Ownasaurus 0:eb2258e8c4b5 142 for(int i = 0;i < 8;i++) // send all 8 bits, one at a time
Ownasaurus 0:eb2258e8c4b5 143 {
Ownasaurus 0:eb2258e8c4b5 144 if((b >> i) & 1)
Ownasaurus 0:eb2258e8c4b5 145 {
Ownasaurus 0:eb2258e8c4b5 146 write_1();
Ownasaurus 0:eb2258e8c4b5 147 }
Ownasaurus 0:eb2258e8c4b5 148 else
Ownasaurus 0:eb2258e8c4b5 149 {
Ownasaurus 0:eb2258e8c4b5 150 write_0();
Ownasaurus 0:eb2258e8c4b5 151 }
Ownasaurus 0:eb2258e8c4b5 152 }
Ownasaurus 0:eb2258e8c4b5 153 }
Ownasaurus 0:eb2258e8c4b5 154
Ownasaurus 1:3c21da72660d 155 void SendIdentity()
Ownasaurus 1:3c21da72660d 156 {
Ownasaurus 1:3c21da72660d 157 // reply 0x05, 0x00, 0x02
Ownasaurus 1:3c21da72660d 158 SendByte(0x05);
Ownasaurus 1:3c21da72660d 159 SendByte(0x00);
Ownasaurus 1:3c21da72660d 160 SendByte(0x02);
Ownasaurus 1:3c21da72660d 161 SendStop();
Ownasaurus 1:3c21da72660d 162 }
Ownasaurus 1:3c21da72660d 163
Ownasaurus 1:3c21da72660d 164 void SendControllerData()
Ownasaurus 1:3c21da72660d 165 {
Ownasaurus 1:3c21da72660d 166 unsigned long data = *(unsigned long*)&n64_data;
Ownasaurus 1:3c21da72660d 167 unsigned int size = sizeof(data) * 8; // should be 4 bytes * 8 = 32 bits
Ownasaurus 1:3c21da72660d 168
Ownasaurus 1:3c21da72660d 169 for(unsigned int i = 0;i < size;i++)
Ownasaurus 1:3c21da72660d 170 {
Ownasaurus 1:3c21da72660d 171 if((data >> i) & 1)
Ownasaurus 1:3c21da72660d 172 {
Ownasaurus 1:3c21da72660d 173 write_1();
Ownasaurus 1:3c21da72660d 174 }
Ownasaurus 1:3c21da72660d 175 else
Ownasaurus 1:3c21da72660d 176 {
Ownasaurus 1:3c21da72660d 177 write_0();
Ownasaurus 1:3c21da72660d 178 }
Ownasaurus 1:3c21da72660d 179 }
Ownasaurus 1:3c21da72660d 180
Ownasaurus 1:3c21da72660d 181 SendStop();
Ownasaurus 1:3c21da72660d 182 }
Ownasaurus 1:3c21da72660d 183
Ownasaurus 1:3c21da72660d 184 // keyboard buttons are stored in cells 2 3 4 5 6 7? cell 0 and 1 are modifiers? cell8 is an F?
Ownasaurus 1:3c21da72660d 185 // the buttons all become 1 if overflow, i think. or in short, [2] == [3]
Ownasaurus 1:3c21da72660d 186 void onKeyboardEvent(uint8_t rep[9])
Ownasaurus 1:3c21da72660d 187 {
Ownasaurus 1:3c21da72660d 188 /*printf("Report = [");
Ownasaurus 1:3c21da72660d 189 for(int i = 0;i < 8;i++)
Ownasaurus 1:3c21da72660d 190 {
Ownasaurus 1:3c21da72660d 191 printf("%X, ", rep[i]);
Ownasaurus 1:3c21da72660d 192 }
Ownasaurus 1:3c21da72660d 193 printf("%X]\r\n", rep[8]);*/
Ownasaurus 1:3c21da72660d 194
Ownasaurus 1:3c21da72660d 195 memset(&n64_data,0,4); // clear controller state
Ownasaurus 1:3c21da72660d 196
Ownasaurus 1:3c21da72660d 197 bool leaveLoop = false;
Ownasaurus 1:3c21da72660d 198
Ownasaurus 1:3c21da72660d 199 for(int index = 2;index < 8;index++)
Ownasaurus 1:3c21da72660d 200 {
Ownasaurus 1:3c21da72660d 201 switch(rep[index]) // the key code
Ownasaurus 1:3c21da72660d 202 {
Ownasaurus 1:3c21da72660d 203 case 0: // no more keys to process
Ownasaurus 1:3c21da72660d 204 leaveLoop = true;
Ownasaurus 1:3c21da72660d 205 break;
Ownasaurus 1:3c21da72660d 206 case KEYBOARD_a:
Ownasaurus 1:3c21da72660d 207 n64_data.a = 1;
Ownasaurus 1:3c21da72660d 208 break;
Ownasaurus 1:3c21da72660d 209 case KEYBOARD_b:
Ownasaurus 1:3c21da72660d 210 n64_data.b = 1;
Ownasaurus 1:3c21da72660d 211 break;
Ownasaurus 1:3c21da72660d 212 case KEYBOARD_z:
Ownasaurus 1:3c21da72660d 213 n64_data.z = 1;
Ownasaurus 1:3c21da72660d 214 break;
Ownasaurus 1:3c21da72660d 215 case KEYBOARD_start:
Ownasaurus 1:3c21da72660d 216 n64_data.start = 1;
Ownasaurus 1:3c21da72660d 217 break;
Ownasaurus 1:3c21da72660d 218 case KEYBOARD_d_up:
Ownasaurus 1:3c21da72660d 219 n64_data.up = 1;
Ownasaurus 1:3c21da72660d 220 break;
Ownasaurus 1:3c21da72660d 221 case KEYBOARD_d_down:
Ownasaurus 1:3c21da72660d 222 n64_data.down = 1;
Ownasaurus 1:3c21da72660d 223 break;
Ownasaurus 1:3c21da72660d 224 case KEYBOARD_d_left:
Ownasaurus 1:3c21da72660d 225 n64_data.left = 1;
Ownasaurus 1:3c21da72660d 226 break;
Ownasaurus 1:3c21da72660d 227 case KEYBOARD_d_right:
Ownasaurus 1:3c21da72660d 228 n64_data.right = 1;
Ownasaurus 1:3c21da72660d 229 break;
Ownasaurus 1:3c21da72660d 230 case KEYBOARD_l:
Ownasaurus 1:3c21da72660d 231 n64_data.l = 1;
Ownasaurus 1:3c21da72660d 232 break;
Ownasaurus 1:3c21da72660d 233 case KEYBOARD_r:
Ownasaurus 1:3c21da72660d 234 n64_data.r = 1;
Ownasaurus 1:3c21da72660d 235 break;
Ownasaurus 1:3c21da72660d 236 case KEYBOARD_c_up:
Ownasaurus 1:3c21da72660d 237 n64_data.c_up = 1;
Ownasaurus 1:3c21da72660d 238 break;
Ownasaurus 1:3c21da72660d 239 case KEYBOARD_c_down:
Ownasaurus 1:3c21da72660d 240 n64_data.c_down = 1;
Ownasaurus 1:3c21da72660d 241 break;
Ownasaurus 1:3c21da72660d 242 case KEYBOARD_c_left:
Ownasaurus 1:3c21da72660d 243 n64_data.c_left = 1;
Ownasaurus 1:3c21da72660d 244 break;
Ownasaurus 1:3c21da72660d 245 case KEYBOARD_c_right:
Ownasaurus 1:3c21da72660d 246 n64_data.c_right = 1;
Ownasaurus 1:3c21da72660d 247 break;
Ownasaurus 1:3c21da72660d 248 // NOTE: THESE BITS MUST BE WRITTEN IN REVERSE ORDER. HIGH BIT IS IN THE LOW POSITION
Ownasaurus 1:3c21da72660d 249 case KEYBOARD_a_up:
Ownasaurus 1:3c21da72660d 250 n64_data.y_axis = 0x0A;
Ownasaurus 1:3c21da72660d 251 break;
Ownasaurus 1:3c21da72660d 252 case KEYBOARD_a_down:
Ownasaurus 1:3c21da72660d 253 n64_data.y_axis = 0x0D;
Ownasaurus 1:3c21da72660d 254 break;
Ownasaurus 1:3c21da72660d 255 case KEYBOARD_a_left:
Ownasaurus 1:3c21da72660d 256 n64_data.x_axis = 0x0D;
Ownasaurus 1:3c21da72660d 257 break;
Ownasaurus 1:3c21da72660d 258 case KEYBOARD_a_right:
Ownasaurus 1:3c21da72660d 259 n64_data.x_axis = 0x0A;
Ownasaurus 1:3c21da72660d 260 break;
Ownasaurus 1:3c21da72660d 261 }
Ownasaurus 1:3c21da72660d 262
Ownasaurus 1:3c21da72660d 263 if(leaveLoop) break;
Ownasaurus 1:3c21da72660d 264 }
Ownasaurus 1:3c21da72660d 265 }
Ownasaurus 1:3c21da72660d 266
Ownasaurus 0:eb2258e8c4b5 267 int main()
Ownasaurus 0:eb2258e8c4b5 268 {
Ownasaurus 1:3c21da72660d 269 pc.printf("Now loaded! SystemCoreClock = %d Hz\r\n", SystemCoreClock);
Ownasaurus 1:3c21da72660d 270 memset(&n64_data,0,4); // start controller in the neutral state
Ownasaurus 1:3c21da72660d 271
Ownasaurus 1:3c21da72660d 272 USBHostKeyboard kb;
Ownasaurus 1:3c21da72660d 273 if (!kb.connect()) {
Ownasaurus 1:3c21da72660d 274 pc.printf("Error: USB kb not found.\n");
Ownasaurus 1:3c21da72660d 275 }
Ownasaurus 1:3c21da72660d 276 // when connected, attach handler called on kb event
Ownasaurus 1:3c21da72660d 277 kb.attach(onKeyboardEvent);
Ownasaurus 0:eb2258e8c4b5 278
Ownasaurus 0:eb2258e8c4b5 279 while(1)
Ownasaurus 0:eb2258e8c4b5 280 {
Ownasaurus 0:eb2258e8c4b5 281 // Set pin mode to input
Ownasaurus 0:eb2258e8c4b5 282 data.input();
Ownasaurus 0:eb2258e8c4b5 283
Ownasaurus 1:3c21da72660d 284 // Read keyboard state?
Ownasaurus 1:3c21da72660d 285 USBHost::poll();
Ownasaurus 1:3c21da72660d 286
Ownasaurus 1:3c21da72660d 287 __disable_irq(); // Disable Interrupts
Ownasaurus 1:3c21da72660d 288 // Read 64 command
Ownasaurus 0:eb2258e8c4b5 289 unsigned int cmd = readCommand();
Ownasaurus 0:eb2258e8c4b5 290
Ownasaurus 0:eb2258e8c4b5 291 my_wait_us_asm(2); // wait a small amount of time before replying
Ownasaurus 1:3c21da72660d 292
Ownasaurus 1:3c21da72660d 293 //-------- SEND RESPONSE
Ownasaurus 0:eb2258e8c4b5 294 // Set pin mode to output
Ownasaurus 0:eb2258e8c4b5 295 data.output();
Ownasaurus 0:eb2258e8c4b5 296
Ownasaurus 0:eb2258e8c4b5 297 switch(cmd)
Ownasaurus 0:eb2258e8c4b5 298 {
Ownasaurus 0:eb2258e8c4b5 299 case 0x00: // identity
Ownasaurus 0:eb2258e8c4b5 300 case 0xFF: // reset
Ownasaurus 1:3c21da72660d 301 SendIdentity();
Ownasaurus 0:eb2258e8c4b5 302 break;
Ownasaurus 0:eb2258e8c4b5 303 case 0x01: // poll for state
Ownasaurus 1:3c21da72660d 304 SendControllerData();
Ownasaurus 1:3c21da72660d 305 break;
Ownasaurus 1:3c21da72660d 306 default:
Ownasaurus 1:3c21da72660d 307 // we do not process the read and write commands (memory pack)
Ownasaurus 1:3c21da72660d 308 break;
Ownasaurus 0:eb2258e8c4b5 309 }
Ownasaurus 1:3c21da72660d 310 __enable_irq(); // Enable Interrupts
Ownasaurus 1:3c21da72660d 311 //-------- DONE SENDING RESPOSE
Ownasaurus 0:eb2258e8c4b5 312 }
Ownasaurus 0:eb2258e8c4b5 313 }