/* receive a clocked byte from the host */
inline char getbyte(void)
{
char count, recdata = 0;
// load 8 clocked bits
for (count = 0; count < 8; count++)
{
// shift data right
recdata >>= 1; // (rotate right)
// wait for high clock
while (!clock);
if (data)
recdata |= 0x80; //set the MSB
// wait for low clock
while (clock);
}
return(recdata);
}
/* end of get byte */
I handed coded into assembly as:
Code:
movlw 0x08 // count = 8
movwf count
BCF 0x03,Carry // reset carry
// we only need to reset the carry once per call
countlp
RRF recdata,1 // recdata >>= 1; shift data right
waitckh btfss clock // wait for high clock
goto waitckh // while (!clock);
btfsc data // if (data) set the MSB
BSF recdata,7 // recdata |= 0x80;
waitckl btfsc clock // wait for low clock
goto waitckl // while (clock);
decfsz count
goto countlp
I can't think of any ways to get the assembly version any faster, or a better way of clocking eight bits in for that matter.
I don't see much improvement possible with your sample code. However, there might be a bug and I modified the code to correct it as follows:
Code:
movlw 0x08 // count = 8
movwf count
countlp ; <-- moved label here.
BCF 0x03,Carry // reset carry
// we only need to reset the carry once per call
RRF recdata,1 // recdata >>= 1; shift data right
waitckh btfss clock // wait for high clock
goto waitckh // while (!clock);
btfsc data // if (data) set the MSB
BSF recdata,7 // recdata |= 0x80;
waitckl btfsc clock // wait for low clock
goto waitckl // while (clock);
decfsz count
goto countlp
The label was moved because you have to clear the carry flag before the RRF instruction or else the carry flag will depend on the result from the previous RRF instruction (unless the entire recdata file register was cleared prior to calling this routine).
In addition, you should consider using interrupts here because the PIC is doing absolutely nothing while waiting for the clock to change. You can use RB0 pin as clock input.
That is correct. Except that you would have to add the "CLRF recdata" ahead of the loop and the "BCF status,carry" would still be required. This is against your objective of reducing code.
Unless the serial clock frequency were faster than 99Khz (11 instructions steps @ 4Mhz), you lose nothing by clearing the carry eight times. You will still waste cycles waiting for the clock to transition unless you're using interrupts.
At this speed (99Khz), interrupts would not be possible because of the overhead of context saving.
BTW, the maximum safe serial clock frequency would be about 62.5Khz (16 instructions steps @ 4Mhz).