I was just trying to visualize what it would take ...
But it seems to have turned into a whole program.
And yup, it uses Melanie's suggestions.
The idea here is to continuously scan the A/D inputs, saving the results to a buffer array.
When it gets a Parallel Load signal (INT), it copies the buffer to the "Shift" array.
Instead of taking the time to actually shift everything each time, it uses an Index counting down from 63 to put each bit out on the pin.
Each bit that is sent, gets replaced with the Input Bit. After it's finished sending all 64 bits, it wraps around and is now sending the data that was shifted IN like a big circular buffer.
It's written for a 16F883, because it has 8+ A/D inputs and an internal 8mhz OSC, but it should work on other chips too (after changing a few things).
I do not have a 16F883, or a CD4021, so this is completely untested.
It does compile, and I think it's close. Should at least be a good starting point.
HTH,Code:'**************************************************************** '* Name : Shift4021.pbp * '* Author : Darrel Taylor * '* Date : 9/9/2008 * '* Version : 1.0 * '* Notes : Target = 16F883, Internal 8mhz OSC * '* Thread : Slave PIC to be used like CD4021 chip * '* http://www.picbasic.co.uk/forum/showthread.php?t=9544 * '**************************************************************** @ __config _CONFIG1, _INTOSCIO & _WDT_OFF & _LVP_OFF & _CPD_OFF DEFINE OSC 8 Clear PloadPin VAR PORTB.0 ; Parallel Load (INT) ClkPin VAR PORTB.1 ; Serial Clock SerInPin VAR PORTB.2 ; Serial Input Pin SerOutPin VAR PORTB.3 ; Serial Output Pin ADbuff VAR BYTE[8] ; Buffers the A/D readings ShiftReg VAR BYTE[8] ; The 64-bit shift register I VAR BYTE ; Index variables X VAR BYTE BitIdx VAR BYTE ADidx VAR BYTE ClkState VAR BIT ; for locating clk edges DataBit VAR BIT ; Serial In read on falling edge INTE VAR INTCON.4 ; Aliases INTF VAR INTCON.1 GoDone VAR ADCON0.1 ;--------------------------------------------------------------------------- Initialize: OSCCON = %01110001 ; Internal 8Mhz OSC INPUT PloadPin ; Input(default), just to make sure INPUT ClkPin INPUT SerInPin LOW SerOutPin ; start with output LOW ADCON0 = %10000001 ; FOSC/32, CH0, ADON ANSELH = 0 ; Turn off upper A/D ports INTF = 0 ; clear INT flag INTE = 1 ; enable INT interrupt ON INTERRUPT goto ParallelLoad ;--------------------------------------------------------------------------- Main: if !GoDone then NextAD ; conversion complete, get results IF ClkPin then ; wait for Rising edge if !ClkState then ClkState = 1 GOSUB NextBit ; Rising edge found, shift data endif else ; wait for falling edge if ClkState then ClkState = 0 DataBit = SerInPin ; falling edge found, read input endif endif GOTO Main ; ---- Cycle thru each A/D channel, one at a time -------------------------- NextAD: ADbuff(ADidx) = ADRESH ; save A/D result ADidx = ADidx + 1 ; point to next A/D channel if ADidx = 8 then ADidx = 0 ; circle around ADCON0 = %10000001 | (ADidx << 2) ; Set the A/D ch. for I = 1 to 5 ; Acquisition time @ NOP NEXT I GoDone = 1 ; Start A/D conversion RETURN DISABLE ; ---- Parallel Load -- copy A/D buffer to Shift register ------------------ ParallelLoad: For X = 0 to 7 ; Copy A/D results ShiftReg(X) = ADbuff(X) NEXT X SerOutPin = ShiftReg.0(63) ; put MSB on Pin BitIdx = 63 ; start shifting from MSB DataBit = SerInPin ; read input bit INTF = 0 ; clear the interrupt flag RESUME ; ---- Put next bit on the output pin -------------------------------------- NextBit: ShiftReg.0(BitIdx) = DataBit ; replace bit with the input data BitIdx = BitIdx - 1 ; point to next bit if BitIdx.7 = 1 then BitIdx = 63 ; circle back to beginning SerOutPin = ShiftReg.0(BitIdx) ; put data on output Pin return





Bookmarks