Beispiel #1
0
// 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);
}
Beispiel #2
0
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) {