In the end I didn't use a 16F84A, but purely because the code space wasn't big enough for what i wanted to do. Also, I never ended up using any special PBP commands, opting to write a subroutine using interrupts that would get the timing perfect. I used an 18F1320 with it's 8Mhz internal clock, but I think 4Mhz would work too.
Here's my code:
Code:INCLUDE "DT_INTS-18.bas" ' Include base interrupt system INCLUDE "ReEnterPBP-18.bas" ' Interrupt Aliases INT0IE var INTCON.4 ' INT0 external interrupt enable bit INTEDG0 var INTCON2.6 ' INT0 external interrupt edge select bit: 1=Rising Edge 0=Falling Edge ' I/O kb_clock var PORTB.0 ' Keyboard clock pin kb_data var PORTB.1 ' Keyboard data pin ' Constants buffer_size CON 32 ' Keyboard buffer size ' Variables packet var word bank0 ' Latest packet from the keyboard packet_index var byte bank0 ' Current bit in keyboard packet buffer var byte[buffer_size] bank0 ' Keyboard data buffer buffer_i_index var byte bank0 ' Current buffer possition for inputs buffer_o_index var byte bank0 ' Current buffer possition for outputs data_received var byte bank0 ' Latest byte retrieved from the buffer n var word bank0 ' Temporary variable for loops temp var word bank0 ' General temporary variable new_data var bit bank0 ' Flag to indicate there is new data from the keyboard parity_bit var bit bank0 ' Parity bit used for PIC->keyboard communication error var bit bank0 ' Flag to indicate an invalid packet ' Initialisation INPUT kb_clock ' Keyboard Clock Pin = Input INPUT kb_data ' Keyboard Data Pin = Input ASM INT_LIST macro ; IntSource Label Type Reset Flag? INT_Handler INT0_INT, _int0_handler, PBP, yes endm INT_CREATE ENDASM INTEDG0=0 ' INT0 Interrupt to Trigger on Falling Edge @ INT_ENABLE INT0_INT main: gosub check_for_new_data IF new_data=1 then ' Do whatever you want with the byte we just received. It is stored in data_received. ENDIF goto main ' Keyboard interrupt handler: Retrieves packet from keyboard int0_handler: packet.11=kb_data ' Store bit packet=packet>>1 ' Rotate the packet so it is ready for the next bit packet_index=packet_index+1 ' Increment packet bit index iF packet_index=11 then ' If packet is complete: gosub check_packet_for_errors ' Check the packet for errors if error=1 then ' If there was an error: packet=0 ' Discard the packet packet_index=0 ' Reset the packet bit index goto int_exit ' Exit the interrupt ENDIF packet_index=0 ' Reset Packet Index packet=packet>>1 ' Discard the start bit buffer[buffer_i_index]=packet.byte0 ' Store just the recieved byte buffer_i_index=buffer_i_index+1 ' Increment buffer input index if buffer_i_index=buffer_size then buffer_i_index=0 ' If end of buffer has been reached, reset the index IF buffer_i_index=buffer_o_index THEN ' If the buffer is full: INT0IE=0 ' Disable Interrupt OUTPUT kb_clock ' Set the keyboard's clock as output low kb_clock ' Set the keyboard's clock line low (tell the keyboard to stall) endif endif int_exit: @ INT_RETURN ' Subroutine to check to see if there is any new data waiting in the keyboard buffer check_for_new_data: IF buffer_o_index!=buffer_i_index then ' If the buffer is not empty: data_received=buffer[buffer_o_index] ' Get the next byte from the buffer new_data=1 ' Set the new data flag buffer_o_index=buffer_o_index+1 ' Increment buffer output index if buffer_o_index=buffer_size then buffer_o_index=0 ' If end of buffer has been reached, reset the index IF INT0IE=0 THEN ' If the buffer was full, its now got a space, so: INPUT kb_clock ' Release the keyboard's clock line INT0IE=1 ' Re-enable the interrupt ENDIF else new_data=0 ' If the buffer is empty, clear the new_data flag endif return ' Subroutine to check the incoming packet for errors check_packet_for_errors: error=0 ' Reset error flag parity_bit=1 ' Set parity bit for start of calculation temp=packet ' Copy the packet to a temp variable so we can play with it if packet.0=1 then ' Check that start bit = 0 error=1 return endif if packet.10=0 then ' Check that stop bit = 1 error=1 return endif temp=temp>>1 ' Discard the start bit for n=0 to 7 ' Calculate what the bit parity should be if packet.0=1 then toggle parity_bit temp=temp>>1 next n if packet.10!=parity_bit then ' Check the parity bit error=1 return endif return




Bookmarks