// ATMEL AVR based s88 feedback unit // // This software was developed using a MEGA162, can be compiled for other AVR's as well // // S88 clock should be connected to INT0 pin, other S88 signals can be routed to any available port // // PINA and PINB ports are used as inputs for the shift register. // // This software emulates a 64 bits s88 unit in the s88_val[] array // // S88_val[0] will hold the inputs from PINB // S88_val[1] will hold the inputs from PINA // // Other S88_val[] values can be calculated, or can be derived using a keyboard matrix scan #include #include #define S88_CLOCK 2 // S88 Clock, PD2 (with INT0) #define S88_LOAD 3 // S88 Latch bus, PD3 #define S88_OUT 4 // S88 Data Output, PD4 #define S88_RESET 5 // S88 Reset, PD5 (not further used in this code, only used to enable port pullup) #define S88_IN 6 // S88 Data Input, PD6 (not further used in this code, only used to enable port pullup) unsigned char col2val[8] = { 0b10000000, // 0 0b01000000, // 1 0b00100000, // 2 0b00010000, // 3 0b00001000, // 4 0b00000100, // 5 0b00000010, // 6 0b00000001, // 7 }; volatile unsigned char s88_val[10]; // this array holds the values of the shift register. volatile unsigned char cnt, // s88 clock counter col, // 3 lowest bits, derived from counter, value 0 .. 7 row, // 5 (or 3 to start with highest bits, derived from counter val; ISR (INT0_vect) // INT0 = S88 clock { if (PIND & _BV(S88_LOAD)) // restart shift register if load signal is active { cnt = 0; // restart is done by starting over at the first element again } col = cnt & 0b00000111; // calculate row and column using counter value, column = last 3 bits row = cnt & 0b00111000; // mask 3 bits for row row >>= 3; // row = now last 3 bits val = s88_val[row] & col2val[col]; // get value based upon row and column if(val) // set dataout bit based upon value { PORTD |= _BV(S88_OUT); } else { PORTD &= ~_BV(S88_OUT); } cnt++; // point to next value in shift register } void setup_hw(void) { MCUCR |= _BV(ISC00) // INT0 enable at rising edge (S88 clock) | _BV(ISC01); GICR = _BV(INT0); // Enable INT0 DDRA = 0x00; // PORTA = input PORTA = 0xff; // enable pull up's for inputs DDRB = 0x00; // PORTB = input PORTB = 0xff; // enable pull up's for inputs DDRD |= _BV(S88_OUT); // S88 Data = output PORTD |= _BV(S88_CLOCK) // enable pull up's for inputs | _BV(S88_LOAD) | _BV(S88_RESET) | _BV(S88_IN); } int main (void) { setup_hw(); // Initialise cnt = 0; // initialize shift register, start with first element sei(); // enable interrupts while(1) // Loop forever, read inputs and fill arrays in memory { s88_val[0] = ~PINB; // inputs are active low, so xor port value s88_val[1] = ~PINA; } return (0); }