From: Drew Fisher Date: Mon, 21 Jun 2010 00:49:36 +0000 (-0700) Subject: Functional code for SNES port 2. X-Git-Url: http://git.zarvox.org/shortlog/year?a=commitdiff_plain;p=usbsnes.git Functional code for SNES port 2. The assembly routine doesn't work. No idea why; I'll rework it later. In the meantime, it's a bad idea to poll the SNES in an interrupt routine, so the interrupt now sets readyToPollSnes every 1/60th of a second instead, and the actual polling code has been placed in getButtons(). This will likely all need a rework when I move to support polling two controllers simultaneously. --- diff --git a/main.c b/main.c index b08d094..44b3cd3 100644 --- a/main.c +++ b/main.c @@ -41,7 +41,7 @@ typedef struct { //uchar id; char x; char y; - uchar buttons; + uchar buttons; // Note: bitstream goes [8...1] } report_t; static report_t buttonState; @@ -49,6 +49,7 @@ static report_t reportBuffer; static uint8_t pollInProgress = 0; static unsigned char idleRate; static uint8_t interrupt_count = 0; +static uint8_t readyToPollSnes = 0; usbMsgLen_t usbFunctionSetup(uchar data[8]) { @@ -69,7 +70,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) { } else if (rq->bRequest == USBRQ_HID_SET_IDLE){ idleRate = rq->wValue.bytes[1]; } - }else{ + } else { /* no vendor specific requests implemented */ } return 0; /* default for not implemented requests: return no data back to host */ @@ -77,18 +78,42 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) { ISR(TIMER1_COMPA_vect) { -/* - if(pollInProgress) // Mutex, to prevent infinite recursion if terribly many USB interrupts (shouldn't happen, but safety net) - return; // We've already started polling the SNES controller, return up the stack so that the original ISR can finish - pollInProgress = 1; // Acquire lock - sei(); // Allow for nested interrupts - namely, USB interrupts. - buttonState.buttons = pollSnes(); - pollInProgress = 0; // Release lock -*/ - if (interrupt_count++ == 60) { - reportBuffer.buttons++; - interrupt_count = 0; + readyToPollSnes = 1; // Set flag for mainloop to poll SNES (better not to do this in an ISR) +} + +static void getButtons() { // Poll the SNES for the button states, arrange bytes appropriately for the descriptor + uint16_t temp= 0x0000; + uint8_t counter = 16; + + PORTC |= _BV(PINC1); + _delay_us(12); + + PORTC &= ~_BV(PINC1); + + for(counter = 0; counter != 16; counter++) { + _delay_us(6); + temp = temp << 1 ; + temp |= (PINC & _BV(PINC2)) ? 0 : 1; + PORTC &= ~_BV(PINC0); + _delay_us(6); + PORTC |= _BV(PINC0); } + + if (temp & 0x0800) + buttonState.y = -127; + //buttonState.x = 127; + else if (temp & 0x0400) + buttonState.y = 127; + //buttonState.x = -127; + else buttonState.y = 0; + + if (temp & 0x0200) + buttonState.x = -127; + else if (temp & 0x0100) + buttonState.x = 127; + else buttonState.x = 0; + buttonState.buttons = ((temp & 0xf000) >> 8) | ((temp & 0x00f0) >> 4) ; + readyToPollSnes = 0; } static void initPins() { @@ -174,10 +199,15 @@ int main(void) //DBG1(0x02, 0, 0); /* debug output: main loop iterates */ wdt_reset(); usbPoll(); + if(readyToPollSnes) { + getButtons(); + } if(usbInterruptIsReady()){ /* called after every poll of the interrupt endpoint */ // Actual code to be executed - updates the HID report with the status of the SNES controller - //reportBuffer.buttons = buttonState.buttons; + reportBuffer.x = buttonState.x; + reportBuffer.y = buttonState.y; + reportBuffer.buttons = buttonState.buttons; // Testing USB reports - change button state every second, incrementing the report buffer by 1. //if(counter++ == 10) {