/*---------------------------------------------------------------------------- ** ** ShiftReg.c ** ** Control of extension shift register ** The extension shift register extends the I/O capability of the micro by ** using a chain of serial-parallel (for outputs) and parallel-serial (for ** inputs) shift registers. The chain shares the same clock and strobe line, ** and the micro has data pin that can be set to input or output to send or ** receive data to/from the chain. ** ** There are two sets of functions. The first set, SetBit() and ReadBit() ** just set and read the shadow registers. Bit setting and bit updating ** will be performed the next time the shift register is updated (every ** 100ms). The second set of functions, SetBitNow() and ReadBitNow() ** perform the action straight away, without the 100ms latency. ** ** The outputs are first in the chain (HC595s), followed by the inputs (HC165s). ** Output data is set on the shift register outputs when the strobe line ** goes high, and inputs are latched in when the strobe line is taken low. ** ** OUTPUTS - 74HC595 INPUTS - 74HC165 ** ----------------- ----------------- ** ** ------- ------- ** Data ---|Ds | Data ---|Ds | ** Clk ---|SHcp | Clk ---|CP | ** 1 ---|/MR Q7|---> 0 ---|/CE Q|---> ** Strb ---|STcp | Strb ---|/PL | ** 1 ---|/OE | | | ** ------- ------- ** ** CONNECTION: ** ** ^ ^ | ** ____ ___|___ ___|___ ___v___ ** |________| HC595 |___| HC595 |___| HC165 |__ ** | data | |_______|q |_______|q |_______|q | ** | | | | | | | | | ** H8S|______|___|__|_________|__|________| | | ** | clk | | | | | ** |______|______|____________|___________| | ** ____| strb | | ** | _______ | ** ---|__10K__|------------------------ ** **--------------------------------------------------------------------------*/ #include "Hardware.h" #include "Onboard.h" #include "ShiftReg.h" // These define the chain dimensions #define CHAIN_LENGTH 24 /* Length of chain in bits */ #define NUM_OUTPUTS 16 /* Number of outputs in chain */ #define NUM_INPUTS 8 /* Number of inputs in chain */ // These are the chain shadow registers. One byte per bit. typedef struct { unsigned char Inputs[NUM_INPUTS]; unsigned char Outputs[NUM_OUTPUTS]; } TShiftRegChain; TShiftRegChain Chain; /*---------------------------------------------------------------------------- // // UpdateChain // // Updates the regsiter chain. Sets outputs and updates inputs. // // Modification Record: // 09-Oct-00 Paul Hills First version. -----------------------------------------------------------------------------*/ void UpdateChain(void) { int i; //--------------------------------------------------------- // Timing diagram: // // Data: IIIIOOOOI0000I0000...I0000OOOOOI // _ _ _ _ // Clk: _____/ \__/ \__/ \...__/ \______ // _ ______________...______ __ // Strb: \_/ \_/ // // Func: 1 32 3 2 3 2 3 2 4 5 // 1 = Dip strobe to latch inputs. // 2 = Rising clock edge reads output from H8 into SR, // and sets input SR output ready to read. // 3 = Data line set to input, input data read. // 4 = Dip strobe. Rising edge clocks new outputs. // 5 = Line left as input to conserve power. //--------------------------------------------------------- // 1. Dip strobe line to latch inputs. SR_CLOCK = 0; SR_STROBE = 0; SR_STROBE = 1; /* Must go high here to allow HC7597 to clock */ for (i = 0 ; i < max(NUM_OUTPUTS,NUM_INPUTS) ; i++) { // 3. If still reading inputs, read input bit into shadow register if (i <= NUM_INPUTS) { SR_INPUT; Chain.Inputs[i] = SR_DATA; } if (i <= NUM_OUTPUTS) { // Set last output bit on data out SR_OUTPUT; SR_DATA = Chain.Outputs[i]; } // 2. One clock SR_CLOCK = 1; SR_CLOCK = 0; } // 4. Now strobe the outputs, leaving strobe high. SR_STROBE = 0; SR_STROBE = 1; // 5. Leave line as an input afterwards SR_INPUT; } /*---------------------------------------------------------------------------- // // InitialiseShiftRegisterChain // // Sets all outputs to the default state, and reads all input states // to preload the shadow registers. // // Modification Record: // 09-Oct-00 Paul Hills First version. -----------------------------------------------------------------------------*/ void InitialiseShiftRegisterChain(void) { int i; // Clear all outputs in shadow register for (i=0 ; i