source: avrstuff/grip2hid/main.cpp@ 5b8c7e2

main
Last change on this file since 5b8c7e2 was 5b8c7e2, checked in by Adrien Destugues <pulkomandy@…>, 5 years ago

grip2hid: make it work (almost) with all 4 pads

  • Property mode set to 100644
File size: 3.9 KB
Line 
1#include <avr/io.h>
2#include <avr/interrupt.h>
3#include <avr/wdt.h>
4#include <avr/pgmspace.h>
5#include <util/delay.h>
6
7#include <string.h>
8#include <stdbool.h>
9
10#include "../libs/usart/usart.h"
11
12#define GRIP_PORT PORTB
13#define GRIP_DDR DDRB
14#define GRIP_PIN PINB
15#define GRIP_DAT_A (1 << 0)
16#define GRIP_CLK_A (1 << 1)
17#define GRIP_DAT_B (1 << 3)
18#define GRIP_CLK_B (1 << 2)
19#define GRIP_DAT_C (1 << 7)
20#define GRIP_CLK_C (1 << 6)
21#define GRIP_DAT_D (1 << 5)
22#define GRIP_CLK_D (1 << 4)
23
24class GrIP
25{
26public:
27 GrIP()
28 {
29 word = 0;
30 count = 0;
31 state = 0;
32 }
33
34 bool PushBit(uint32_t bit)
35 {
36 word = (word << 1) | (bit & 1);
37 count++;
38
39 switch (state) {
40 case 0:
41 if ((word & 0x3F) != 0x1F) return false;
42 count = 6;
43 state = 1;
44 break;
45 case 1:
46 if (count == 24) {
47 state = 0;
48 count = 0;
49 return true;
50 }
51 break;
52 }
53
54 return false;
55 }
56
57 void Dump() {
58 USARTWriteHex(word >> 16);
59 USARTWriteHex(word >> 8);
60 USARTWriteHex(word);
61 }
62
63private:
64 uint32_t word;
65 uint8_t count;
66 uint8_t state;
67};
68
69
70int main() {
71 wdt_enable(WDTO_2S);
72
73 // GrIP input
74 GRIP_PORT = 0xFF; // Enable pull-ups
75 GRIP_DDR = 0; // Port as input
76
77 USARTInit();
78 USARTWriteChar('h');
79 USARTWriteChar('\r');
80 USARTWriteChar('\n');
81
82 // Initial value of oldv for edge detection
83 uint8_t oldv = GRIP_PIN;
84
85 for (;;) {
86 // Because the CPU is too slow, if we try to scan all pads at once we
87 // don't manage to decode them (missed transitions). So we scan them
88 // one at a time.
89 // To scan all 4 gamepads this will take about 4 milliseconds, which
90 // is not the best we could do, but is okay. When we have the real
91 // hardware (with the CPU running at full 16MHz speed instead of crappy
92 // 1MHz here), we can try to interleave them again (one just has to put
93 // them all into a single for loop instead of separate loops for each).
94 // Then we get to 1ms to scan all 4 pads in parallel, cool! And it
95 // also fixes the problem mentionned below that when less pads are
96 // connected, it will not slowdown waiting for one of them to timeout.
97
98 // FIXME the loop to 255 here to wait for a bit isn't too nice. We
99 // should rather use a timer with a known period?
100 // Process pad1
101 GrIP pad;
102 uint8_t i;
103 for (i = 0; i < 255; i++) {
104 wdt_reset();
105
106 uint8_t newv = GRIP_PIN;
107
108 if (!(newv & GRIP_CLK_A)) { // clock is down
109 if (oldv & GRIP_CLK_A) { // and it was up at previous read
110 // Read bit
111 uint32_t bit = (newv & GRIP_DAT_A) != 0;
112 if (pad.PushBit(bit)) {
113 break;
114 }
115 }
116 }
117 oldv = newv;
118 }
119
120 pad.Dump();
121 USARTWriteChar(' ');
122
123 // Process pad 2
124 for (i = 0; i < 255; i++) {
125 wdt_reset();
126
127 uint8_t newv = GRIP_PIN;
128 if (!(newv & GRIP_CLK_B)) { // clock is down
129 if (oldv & GRIP_CLK_B) { // and it was up at previous read
130 // Read bit
131 uint32_t bit = (newv & GRIP_DAT_B) != 0;
132 if (pad.PushBit(bit)) {
133 break;
134 }
135 }
136 }
137 oldv = newv;
138 }
139
140 pad.Dump();
141 USARTWriteChar(' ');
142
143 // Process pad 3
144 for (i = 0; i < 255; i++) {
145 wdt_reset();
146
147 uint8_t newv = GRIP_PIN;
148 if (!(newv & GRIP_CLK_C)) { // clock is down
149 if (oldv & GRIP_CLK_C) { // and it was up at previous read
150 // Read bit
151 uint32_t bit = (newv & GRIP_DAT_C) != 0;
152 if (pad.PushBit(bit)) {
153 break;
154 }
155 }
156 }
157 oldv = newv;
158 }
159
160 pad.Dump();
161 USARTWriteChar(' ');
162
163 // Process pad 4
164 for (i = 0; i < 255; i++) {
165 wdt_reset();
166
167 uint8_t newv = GRIP_PIN;
168 if (!(newv & GRIP_CLK_D)) { // clock is down
169 if (oldv & GRIP_CLK_D) { // and it was up at previous read
170 // Read bit
171 uint32_t bit = (newv & GRIP_DAT_D) != 0;
172 if (pad.PushBit(bit)) {
173 break;
174 }
175 }
176 }
177 oldv = newv;
178 }
179
180 pad.Dump();
181 USARTWriteChar('\r');
182 USARTWriteChar('\n');
183 }
184
185 return 0;
186}
187
188
Note: See TracBrowser for help on using the repository browser.