// This should be called on an interrupt timer whose period // is at most 1/(60*4) seconds (the number of rows times // POV time) void leddriver::tickLEDs() { int x = 0; // For looping // Turn of LEDS by setting current row to high impedance (aka input mode) highZRows(); // Increment row being displayed curLEDrow++; if (curLEDrow >= 4) curLEDrow = 0; // Push data out shift register // Hopefully gcc unrolls this for loop for(x = 0; x < 8; x++) { // Zero out data bit dataLow(); // Add 8 to register if led is active (mod 2 to convert nonzero to 1) dataSet(ledMatrix[curLEDrow] & (1 << x)); // Latch Data In latchHigh(); rlatchLow(); latchLow(); rlatchHigh(); } // Reenable output on new row by outputing a 'sink' on the current row sinkRow(curLEDrow); }
static void timerAction(void) { /* restart timer */ outp(COUNT_UP, TCNT2); /* value counts up from this to zero */ if (kbd_state < IDLE_END) { // start, wait_rel or ready to tx dataHigh(); if (!(kbd_flags & FLA_CLOCK_HIGH)) { kbd_flags |= FLA_CLOCK_HIGH; clockHigh(); return; } /* if clock held low, then we must prepare to start rxing */ if (!readClockPin()) { kbd_state = IDLE_WAIT_REL; return; } switch(kbd_state) { case IDLE_START: kbd_state = IDLE_OK_TO_TX; return; case IDLE_WAIT_REL: if (!readDataPin()) { /* PC wants to transmit */ kbd_state = RX_START; return; } /* just an ack or something */ kbd_state = IDLE_OK_TO_TX; return; case IDLE_OK_TO_TX: if (kbd_flags & FLA_TX_BYTE) { dataLow(); kbd_state = TX_START; } return; } return; } else // end < IDLE_END if (kbd_state < RX_END) { if (!(kbd_flags & FLA_CLOCK_HIGH)) { kbd_flags |= FLA_CLOCK_HIGH; clockHigh(); return; } /* at this point clock is high in preparation to going low */ if (!readClockPin()) { /* PC is still holding clock down */ dataHigh(); kbd_state = IDLE_WAIT_REL; return; } switch(kbd_state) { case RX_START: /* PC has released clock line */ /* we keep it high for a good half cycle */ kbd_flags &= ~FLA_RX_BAD; kbd_state++; return; case RX_RELCLK: /* now PC has seen clock high, show it some low */ break; case RX_DATA0: kbd_flags &= ~FLA_RX_BYTE; if (readDataPin()) { rx_byte = 0x80; parity = 1; } else { parity = 0; rx_byte = 0; } break; /* end clk hi 1 */ case RX_DATA1: case RX_DATA2: case RX_DATA3: case RX_DATA4: case RX_DATA5: case RX_DATA6: case RX_DATA7: rx_byte >>= 1; if (readDataPin()) { rx_byte |= 0x80; parity++; } break; /* end clk hi 2 to 8 */ case RX_PARITY: if (readDataPin()) { parity++; } if (!(parity & 1)) { /* faulty, not odd parity */ kbd_flags |= FLA_RX_BAD; } break; /* end clk hi 9 */ case RX_STOP: if (!readDataPin()) { /* if stop bit not seen */ kbd_flags |= FLA_RX_BAD; } if (!(kbd_flags & FLA_RX_BAD)) { dataLow(); kbd_flags |= FLA_RX_BYTE; } break; /* end clk hi 10 */ case RX_SENT_ACK: dataHigh(); kbd_state = IDLE_START; /* remains in clk hi 11 */ return; } clockLow(); kbd_flags &= ~(FLA_CLOCK_HIGH); kbd_state++; return; } else // end < RX_END if (kbd_state < TX_END) {