I wonder if you have a shiftInByte macro lying around some ware?
Here is some code that I put together for a shift in macro. Note that there is one additional parameter (compared to shiftOut) which tells the macro whether to read the data before the leading edge of the clock or after the leading edge of the clock. Which you should use depends on the external device that you're dealing with.
#define PRECLOCK 0 // sample data before clock
#define POSTCLOCK 1 sample data after clock
#define bitRead(pin) ({ \
uint8_t cnt = ((pin) < 8) ? (pin) : ((pin) - 8); \
uint8_t val = ((uint16_t)(((pin) < 8) ? PIND : PINB) >> cnt) & 0x01; \
val; \
})
#define shiftInBit(dataPin, clockPin, sampleWhen, bit) ({ \
uint8_t val; \
if ((sampleWhen) == PRECLOCK) \
val = bitRead(dataPin); \
bitWrite(clockPin, HIGH); \
if ((sampleWhen) != PRECLOCK) \
val = bitRead(dataPin); \
bitWrite(clockPin, LOW); \
val << (bit); \
})
#define shiftInByte(dataPin, clockPin, sampleWhen, bitOrder) ({ \
uint8_t val = 0; \
val |= shiftInBit(dataPin, clockPin, sampleWhen, ((bitOrder) == LSBFIRST ?0:7)); \
val |= shiftInBit(dataPin, clockPin, sampleWhen, ((bitOrder) == LSBFIRST ?1:6)); \
val |= shiftInBit(dataPin, clockPin, sampleWhen, ((bitOrder) == LSBFIRST ?2:5)); \
val |= shiftInBit(dataPin, clockPin, sampleWhen, ((bitOrder) == LSBFIRST ?3:4)); \
val |= shiftInBit(dataPin, clockPin, sampleWhen, ((bitOrder) == LSBFIRST ?4:3)); \
val |= shiftInBit(dataPin, clockPin, sampleWhen, ((bitOrder) == LSBFIRST ?5:2)); \
val |= shiftInBit(dataPin, clockPin, sampleWhen, ((bitOrder) == LSBFIRST ?6:1)); \
val |= shiftInBit(dataPin, clockPin, sampleWhen, ((bitOrder) == LSBFIRST ?7:0)); \
val; \
})
One problem with this macro, and shiftOutByte for that matter, is that the clock polarity if fixed. By this I mean that the leading edge of the clock pulse is always a low-to-high transition. It would be better if both macros simply toggled the clock output. That would allow you to set the polarity of the clock signal by setting the initial state of the clock line. The shiftOut() function has the same shortcoming.
The newer AVR chips support toggling an output pin by writing a 1 to the corresponding bit of the PINx register. (The mega8 does not have this feature but the mega168 and mega328P both do.) A macro like the one below could be used to toggle an output pin on the AVR devices that support this feature.
#define togpin(pin) sbi((pin)<8 ? PIND:PINB, (pin) - ((pin)<8 ? 0:8))