;********************************************************************** ; Refer to the MPASM User's Guide for additional information on * ; features of the assembler and linker (Document DS33014). * ; * ; Refer to the respective PICmicro data sheet for additional * ; information on the instruction set. * ; * ;********************************************************************** ; * ; Filename: f877a.asm * ; Date: June 6, 2007 * ; File Version: 0.1 * ; * ; Author: Original Code from DLP Design * ; was written in C by Don L. Powrie * ; * ; Rewritten in Assembly by Craig Van Degrift * ; to include bulk port and D/A reading * ; and adding additional 1-wire sensor * ; routines (Search, Match ROM,...) * ; * ; Also added commands to control Mavica CD-500 * ; camera via its ACC port. * ; * ; See http://yosemitefoothills.com/Electronics * ; and http://yosemitefoothills.com/Mavica * ; * ;********************************************************************** ; * ; Files required: p16f877a.inc * ; * ; * ;********************************************************************** ; * ; Notes: Compiled and linked using * ; * ; gpasm f877a.asm -c * ; gplink -m -s 16f877a.lkr -c f877a.o -a inhx8m * ; * ; The code initializes the 16F877A and then awaits commands that * ; start with a command length byte and end with a check byte * ; obtained by XORing all bytes up to the check byte. The command * ; length byte does not count itself or the final check byte. * ; * ; The second byte is the command byte. Other bytes vary according * ; to the command as follows, listed by the corresponding labels * ; in the assembly code: * ; * ; 0x55 Read_port_A * ; Byte 3: 0x28 + Pin number * ; Byte 4: Block count with 0 = 256 * ; Byte 5: Block size with 0 = 256 * ; Byte 6: Delay in microseconds between samples * ; Returns Block count * Block size bytes * ; * ; 0x56 Write_port_A * ; Byte 3: Byte with bits to set on the 8 pins * ; * ; 0x59 Read_port_C * ; Byte 3: 0x38 + Pin number * ; Byte 4: Block count with 0 = 256 * ; Byte 5: Block size with 0 = 256 * ; Byte 6: Delay in microseconds between samples * ; Returns Block count * Block size bytes * ; * ; 0x5A Write_port_C * ; Byte 3: Byte with bits to set on the 8 pins * ; * ; 0x5B Read_port_D * ; Byte 3: 0x40 + Pin number * ; Byte 4: Block count with 0 = 256 * ; Byte 5: Block size with 0 = 256 * ; Byte 6: Delay in microseconds between samples * ; Returns Block count * Block size bytes * ; * ; 0x5C Write_port_D * ; Byte 3: Byte with bits to set on the 8 pins * ; * ; 0xA5 Read_pins * ; Byte 3: 0x28 + Port + Pin number * ; (Port A = 0, Port B = 1, ... Port E = 5) * ; Returns byte with pin setting (high = 1, low = 0) * ; * ; 0xA6 Set_pins * ; Byte 3: 0x28 + Port + Pin number * ; (Port A = 0, Port B = 1, ... Port E = 5) * ; Byte 4: Pin setting (high = 1, low = 0) * ; * ; 0xA7 Return_board_id * ; No additional bytes in command * ; Returns "2232PB" * ; * ; 0xA8 Setup_AtoD * ; Byte 3: ADCON1 (See code & PIC16F877A Ref for details) * ; Byte 4: ADCON0 (See code & PIC16F877A Ref for details) * ; * ; 0xA9 Run_AtoD * ; Byte 3: Analog input port (0-5) * ; Byte 4: Block count with 0 = 256 * ; Byte 5: Block size with 0 = 256 * ; Byte 6: Delay in microseconds between samples * ; Returns Block count * Block size bytes * ; * ; 0xAA Read_EEPROM * ; Byte 3: Address in EEPROM to read (0 - 255) * ; Returns byte from the address * ; * ; 0xAB Write_EEPROM * ; Byte 3: Address in EEPROM to write to (0 - 255) * ; Byte 4: Data byte to be written * ; * ; 0xAC Check_temp_sensor_presence * ; Byte 3: 0x28 + Port + Pin number * ; (Port A = 0, Port B = 1, ... Port E = 5) * ; Returns byte indicating status of sensor * ; (99 = all ok, 02 = No sensor, 08 = Short-circuit) * ; * ; 0xAD Read_temp * ; Byte 3: 0x28 + Port + Pin number * ; (Port A = 0, Port B = 1, ... Port E = 5) * ; Returns 9 bytes from scratch pad * ; (See DS18S20 Ref for details) * ; * ; 0xAF Loopback * ; Byte 3: Test byte to be echoed * ; Returns test byte * ; * ; 0xBA Read_temp_sensor_ROM * ; Byte 3: 0x28 + Port + Pin number * ; (Port A = 0, Port B = 1, ... Port E = 5) * ; Returns 8-byte ROM code from sensor * ; (See DS18S20 Ref for details) * ; * ; 0xBB Search_temp_sensors * ; Byte 3: 0x28 + Port + Pin number * ; Returns 8-byte ROM codes for all sensors on the pin * ; followed by 8 bytes of zeros * ; If problem reading sensors, returns 8 bytes repeating * ; the sensor status code (99, 02, or 08, see below) * ; * ; 0xBC Check_temp_sensor_presence_match * ; Byte 3: 0x28 + Port + Pin number * ; (Port A = 0, Port B = 1, ... Port E = 5) * ; Bytes 4-11: ROM code for sensor to be used * ; Returns byte indicating status of sensor * ; (99 = all ok, 02 = No sensor, 08 = Short-circuit) * ; * ; 0xBD Read_temp_match * ; Byte 3: 0x28 + Port + Pin number * ; (Port A = 0, Port B = 1, ... Port E = 5) * ; Bytes 4-11: ROM code for sensor to be used * ; Returns 9 bytes from scratch pad * ; (See DS18S20 Ref for details) * ; * ; * ; NOTE: For speed reasons, the mavica commands are hard-coded * ; to work only with Port A, Pin 0 * ; * ; 0xC0 Initialize_mavica * ; Returns 1 byte with timing loop count * ; * ; 0xC1 Read_mavica_bytes * ; Byte 3: Number of repetitions, 0x00 = 256 * ; Returns all 8 bytes of each group * ; * ; 0xC2 Send_mavica_byte * ; Byte 3: Number of repetitions, 0x00 = 256 * ; Byte 4: Control code (byte 2 of 8 in group) * ; 0x00 Idles * ; 0x19 Zoom toward telephoto * ; 0x29 Zoom toward telephoto * ; 0x59 Zoom toward wide-angle * ; 0x69 Zoom toward wide-angle * ; 0x4a Perform auto focus * ; 0x5a Release shutter * ; 0x7a Turn camera off * ; Returns last 5 bytes of each 8-byte group * ; * ;********************************************************************** list p=16f877a ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_ON & _BODEN_OFF & _PWRTE_OFF & _HS_OSC & _WRT_OFF & _LVP_ON & _CPD_OFF ; '__CONFIG' directive is used to embed configuration data within .asm file. ; The labels following the directive are located in the respective .inc file. ; See respective data sheet for additional information on configuration word. ;***** VARIABLE DEFINITIONS (examples) ; example of using Shared Uninitialized Data Section INT_VAR UDATA_SHR 0x71 Loop_counter_0 RES 1 Loop_counter_1 RES 1 Returned_byte RES 1 Shared_temp RES 1 ; example of using Uninitialized Data Section TEMP_VAR UDATA 0x20 ; explicit address specified is not required Current_LED_state RES 1 LED_delay_count_lo_byte RES 1 LED_delay_count_hi_byte RES 1 LED_flash_count RES 1 Command_byte_0 RES 1 Command_byte_1 RES 1 Command_byte_2 RES 1 Command_byte_3 RES 1 Command_byte_4 RES 1 Command_byte_5 RES 1 Command_byte_6 RES 1 Command_byte_7 RES 1 Command_byte_8 RES 1 Command_byte_9 RES 1 Command_byte_10 RES 1 Command_byte_11 RES 1 Command_byte_12 RES 1 Pin_reading_1 RES 1 Pin_reading_2 RES 1 Command_received_ok RES 1 Bytes_received RES 1 Port_and_pin RES 1 TRISC_copy RES 1 mS_to_wait RES 1 uS_to_wait RES 1 Byte_for_USB RES 1 Temp_1 RES 1 Temp_2 RES 1 Temp_3 RES 1 Temp_4 RES 1 Temp_5 RES 1 Temp_6 RES 1 Temp_7 RES 1 Temp_8 RES 1 Temp_9 RES 1 Temp_sensor_status RES 1 Loop_count RES 1 Nbr_bytes_for_sensor RES 1 Nbr_of_bits_for_sensor RES 1 Nbr_of_leftover_bits RES 1 Nbr_of_bits_to_send RES 1 Nbr_of_bits_to_read RES 1 Byte_with_bits_for_sensor RES 1 Byte_with_bits_from_sensor RES 1 Loops_per_bit RES 1 Last_discrepancy RES 1 Search_done RES 1 No_discrepancy RES 1 Bit_index RES 1 Discrepancy_marker RES 1 ROM_code RES 1 ROM_code_1 RES 1 ROM_code_2 RES 1 ROM_code_3 RES 1 ROM_code_4 RES 1 ROM_code_5 RES 1 ROM_code_6 RES 1 ROM_code_7 RES 1 ROM_byte_count RES 1 Byte_count RES 1 ROM_array_byte RES 1 ROM_array_byte_bit RES 1 Camera_handshake RES 1 Remote_handshake RES 1 ;********************************************************************** RESET_VECTOR CODE 0x000 ; processor reset vector MOVLW 00 MOVWF PCLATH ; Clear reg 0A (PCLATH, upper 5 bits of program counter) GOTO Init ; Go to initialization NOP MAIN CODE Wait_mS ; Start of wait milliseconds loop MOVLW mS_to_wait MOVWF FSR ; Set indirect addressing pointing to number of mS to delay MOVF INDF,W ; Copy mS remaining to W BTFSC STATUS,2 GOTO Wait_mS_4 ; Return if countdown complete Wait_mS_1 MOVLW 06 MOVWF Loop_counter_1 Wait_mS_2 MOVLW 0xBF MOVWF Loop_counter_0 Wait_mS_3 CLRWDT DECFSZ Loop_counter_0,F GOTO Wait_mS_3 DECFSZ Loop_counter_1,F GOTO Wait_mS_2 MOVLW 7A MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 ; Extra loop NOP NOP CLRWDT DECFSZ INDF,F ; Decrement mS remaining GOTO Wait_mS_1 ; Wait another millisecond Wait_mS_4 RETLW 00 Toggle_LED INCF LED_delay_count_lo_byte,F BTFSC STATUS,2 INCF LED_delay_count_hi_byte,F MOVF LED_delay_count_hi_byte,W SUBLW 0xE9 BTFSC STATUS,0 GOTO Toggle_LED_3 XORLW 0xFF BTFSS STATUS,2 GOTO Toggle_LED_1 MOVF LED_delay_count_lo_byte,W SUBLW 60 BTFSC STATUS,0 GOTO Toggle_LED_3 Toggle_LED_1 CLRF LED_delay_count_hi_byte CLRF LED_delay_count_lo_byte MOVF Current_LED_state,F BTFSS STATUS,2 GOTO Toggle_LED_2 MOVLW 01 MOVWF Current_LED_state BSF STATUS,5 ; BANK 1 BCF TRISE,0 ; TRISE, pin 0 set for output BCF STATUS,5 ; BANK 0 BCF PORTE,0 ; PORTE, pin 0, (LED) set low GOTO Toggle_LED_3 Toggle_LED_2 CLRF Current_LED_state BSF STATUS,5 ; BANK 1 BCF TRISE,0 ; TRISE, pin 0 set for output BCF STATUS,5 ; BANK 0 BSF PORTE,0 ; PORTE, pin 0 (LED) set high Toggle_LED_3 BCF PCLATH,3 BCF PCLATH,4 GOTO Process_command_1 ; Back to start of processing loop Read_USB BSF STATUS,5 ; BANK 1 BSF TRISB,4 ; Set TRISB, pin 4 for input MOVLW 00 BCF STATUS,5 ; BANK 0 BTFSC PORTB,4 ; Set PORTB, pin 4 (RXF#) high MOVLW 01 SUBLW 01 BTFSC STATUS,2 GOTO Read_USB MOVLW 0xFF BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set TRISD for input BCF TRISB,1 ; Set TRISB, pin 1 for output BCF STATUS,5 ; BANK 0 BCF PORTB,1 ; Set PORTB, pin 1 (RD#) low MOVLW 01 ; Delay 1 uS MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 MOVLW 0xFF BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set TRISD for input BCF STATUS,5 ; BANK 0 MOVF PORTD,W ; Read PORTD into W MOVWF Temp_3 ; Store new byte in reg 63 BSF STATUS,5 ; BANK 1 BCF TRISB,1 ; Set TRISB, pin 1 for output BCF STATUS,5 ; BANK 0 BSF PORTB,1 ; Set PORTB, pin 1 (RD#) high MOVF Temp_3,W MOVWF Returned_byte RETLW 00 Send_byte MOVLW 00 BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set TRISD for all output Check_TXE BSF TRISE,2 ; Set TRISE, pin 2 (TXE#) for input MOVLW 00 BCF STATUS,5 ; BANK 0 BTFSC PORTE,2 ; Test PORTE, bit 2 (TXE#) for low MOVLW 01 ; TXE# must still be high, so prevent loop from ending SUBLW 01 BTFSS STATUS,2 ; Test for zero result, skip if was zero GOTO Put_byte_on_D ; TXE# must have gone low signifying ready for data, so jump out of loop BSF STATUS,5 ; BANK 1 GOTO Check_TXE ; Keep waiting for TXE# to go low Put_byte_on_D MOVLW 00 BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set reg 88 (TRISD) for all output BCF STATUS,5 ; BANK 0 MOVF Byte_for_USB,W MOVWF PORTD ; Set PORTD BSF STATUS,5 ; BANK 1 Strobing WR BCF TRISB,2 ; Set TRISB, pin 2 for output BCF STATUS,5 ; BANK 0 BCF PORTB,2 ; Clear PORTB, pin 2 (WR to low signifying valid data on lines) BSF PORTB,2 ; Set PORTB, pin 2 (WR to high again) MOVLW 0xFF BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set TRISD for all input BCF STATUS,5 ; BANK 0 RETLW 00 Send_immediate ; Start of Send Immediate by strobing PortE, bit 1, (SI/WU) low momentarily BSF STATUS,5 ; BANK 1 BCF TRISE,1 ; Set TRISE, pin 1 for output BCF STATUS,5 ; BANK 0 BCF PORTE,1 ; Set PORTE, pin 1 to low BSF STATUS,5 ; BANK 1 BCF TRISE,1 ; Set TRISE, pin 1 for output (This seems unnecessary) BCF STATUS,5 ; BANK 0 BSF PORTE,1 ; Set PORTE, pin 1 to high RETLW 00 Receive_command ; Start of receive_packet() CALL Read_USB ; Read a byte (command byte count), result Returned_byte MOVF Returned_byte,W MOVWF Temp_5 ; Save it to be decremented as bytes are read MOVF Temp_5,W MOVWF Command_byte_0 ; Save the first command byte (nbr of command bytes) MOVF Temp_5,W MOVWF Temp_4 ; Also save it to be used in checksum calculation MOVLW 01 MOVWF Bytes_received ; Initialize Bytes_received count Get_next_byte MOVF Temp_5,W DECF Temp_5,F ; Decrement the byte counter and see if zero XORLW 00 BTFSC STATUS,2 ; Skip if not yet zero GOTO Start_checksum_calc ; Finished getting command bytes - do checksum MOVF Bytes_received,W INCF Bytes_received,F ADDLW Command_byte_0 ; Prepare for indirect addressing of command bytes MOVWF Temp_2 ; Save the address while getting next byte CALL Read_USB MOVF Temp_2,W MOVWF FSR ; Put in indirect addressing register MOVF Returned_byte,W MOVWF INDF ; Put W in address pointed to by indirect addressing register GOTO Get_next_byte Start_checksum_calc CLRF Temp_6 ; Initialize by clearing Temp_6 and Temp_7 CLRF Temp_7 Calculate_checksum MOVLW 01 ADDWF Temp_4,W ; See if done yet SUBWF Temp_7,W BTFSC STATUS,0 GOTO Compare_checksums ; Checksum calculation is done MOVLW Command_byte_0 ; Prepare indirect addressing ADDWF Temp_7,W ; Add counter MOVWF FSR MOVF INDF,W ; Get the next byte XORWF Temp_6,F INCF Temp_7,F GOTO Calculate_checksum ; Process next command byte Compare_checksums ; Compare calculated checksum with command CALL Read_USB ; Get checksum from command string MOVF Temp_6,W SUBWF Returned_byte,W BTFSS STATUS,2 ; Test zero same, skip if yes GOTO Checksum_error ; Checksum error Look_for_extra_bytes ; No error MOVLW 0xA6 ; Delay 166*0.6=100 microseconds MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP BSF STATUS,5 ; BANK 1 BSF TRISB,4 ; Set TRISB, pin 4 (RXF#) to input MOVLW 00 ; Put 0 in W and later see if it is unchanged BCF STATUS,5 ; BANK 0 BTFSC PORTB,4 ; Test PORTB, pin 4 (RXF#), skip if low MOVLW 01 ; Load a 01 into W to signify RXF# is high XORLW 00 ; **** This seems unnecessarily complicated **** BTFSS STATUS,2 GOTO Received_ok ; All ok, RXF# is high so no additional bytes MOVLW 05 ; RXF# is low so wait a bit and get excess bytes MOVWF mS_to_wait CALL Wait_mS Check_RXF ; Check RXF# again BSF STATUS,5 ; BANK 1 BSF TRISB,4 ; Set TRISB, pin 4 (RXF#) to input MOVLW 00 BCF STATUS,5 ; BANK 0 BTFSC PORTB,4 ; Test PORTB, pin 4 (RXF#), skip if low MOVLW 01 XORLW 00 BTFSS STATUS,2 GOTO Overrun_error ; RXF# is now high so no more bytes incoming MOVLW 05 MOVWF mS_to_wait CALL Wait_mS CALL Read_USB ; Read byte and check RXF# again GOTO Check_RXF Overrun_error ; Send 0xAB to indicate excess bytes flushed after command end MOVLW 0xAB MOVWF Byte_for_USB CALL Send_byte CLRF Command_received_ok GOTO Finish_receive_command Received_ok ; Send 0x55 to indicate commmand received ok MOVLW 55 MOVWF Byte_for_USB CALL Send_byte MOVLW 0xA6 ; Delay 166*0.6=100 uS MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP MOVLW 01 MOVWF Command_received_ok GOTO Finish_receive_command Checksum_error ; Send 0xAA to indicate checksum error MOVLW 0xAA MOVWF Byte_for_USB CALL Send_byte CLRF Command_received_ok Finish_receive_command ; Tell FT2232C Send Immediate CALL Send_immediate ; Flush status byte in FIFO buffer to PC BCF PCLATH,3 ; These are necessary only if the following GOTO command BCF PCLATH,4 ; is located above locating 0x1FF GOTO Return_board_id ; Process first command of command loop Do_setup_AtoD MOVF Command_byte_2,W ; Copy A/D PCFG code=A/D number to W IORLW 80 ; Set A/D Format bit (ADFM) BSF STATUS,5 ; BANK 1 MOVWF ADCON1 ; Copy to ADCON1 BCF STATUS,5 ; BANK 0 MOVF ADCON0,W ; Merge ADCON0 with Command_byte_3 (divisor) ANDLW 38 IORWF Command_byte_3,W MOVWF ADCON0 ; Copy to ADCON0 BCF PCLATH,3 BCF PCLATH,4 GOTO Finish_setup_AtoD Set_pin_high MOVLW 28 ; Create jump size for Computed GOTO SUBWF Port_and_pin,W ADDLW 0xDF BTFSC STATUS,0 GOTO Finish_set_pin_high ADDLW 21 GOTO Pin_high_computed_GOTO Set_pin_A0_high BSF STATUS,5 ; BANK 1 BCF TRISA,0 BCF STATUS,5 ; BANK 0 BSF PORTA,0 GOTO Finish_set_pin_high Set_pin_A1_high BSF STATUS,5 ; BANK 1 BCF TRISA,1 BCF STATUS,5 ; BANK 0 BSF PORTA,1 GOTO Finish_set_pin_high Set_pin_A2_high BSF STATUS,5 ; BANK 1 BCF TRISA,2 BCF STATUS,5 ; BANK 0 BSF PORTA,2 GOTO Finish_set_pin_high Set_pin_A3_high BSF STATUS,5 ; BANK 1 BCF TRISA,3 BCF STATUS,5 ; BANK 0 BSF PORTA,3 GOTO Finish_set_pin_high Set_pin_A4_high BSF STATUS,5 ; BANK 1 BCF TRISA,4 BCF STATUS,5 ; BANK 0 BSF PORTA,4 GOTO Finish_set_pin_high Set_pin_A5_high BSF STATUS,5 ; BANK 1 BCF TRISA,5 BCF STATUS,5 ; BANK 0 BSF PORTA,5 GOTO Finish_set_pin_high Set_pin_B0_high BSF STATUS,5 ; BANK 1 BCF TRISB,0 BCF STATUS,5 ; BANK 0 BSF PORTB,0 GOTO Finish_set_pin_high Set_pin_B5_high BSF STATUS,5 ; BANK 1 BCF TRISB,5 BCF STATUS,5 ; BANK 0 BSF PORTB,5 GOTO Finish_set_pin_high Set_pin_C0_high BCF TRISC_copy,0 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BSF PORTC,0 GOTO Finish_set_pin_high Set_pin_C1_high BCF TRISC_copy,1 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BSF PORTC,1 GOTO Finish_set_pin_high Set_pin_C2_high BCF TRISC_copy,2 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BSF PORTC,2 GOTO Finish_set_pin_high Set_pin_C3_high BCF TRISC_copy,3 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BSF PORTC,3 GOTO Finish_set_pin_high Set_pin_C4_high BCF TRISC_copy,4 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BSF PORTC,4 GOTO Finish_set_pin_high Set_pin_C5_high BCF TRISC_copy,5 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BSF PORTC,5 GOTO Finish_set_pin_high Set_pin_C6_high BCF TRISC_copy,6 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BSF PORTC,6 GOTO Finish_set_pin_high Set_pin_C7_high BCF TRISC_copy,7 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BSF PORTC,7 GOTO Finish_set_pin_high Set_pin_D0_high BSF STATUS,5 ; BANK 1 BCF TRISD,0 BCF STATUS,5 ; BANK 0 BSF PORTD,0 GOTO Finish_set_pin_high Set_pin_D1_high BSF STATUS,5 ; BANK 1 BCF TRISD,1 BCF STATUS,5 ; BANK 0 BSF PORTD,1 GOTO Finish_set_pin_high Set_pin_D2_high BSF STATUS,5 ; BANK 1 BCF TRISD,2 BCF STATUS,5 ; BANK 0 BSF PORTD,2 GOTO Finish_set_pin_high Set_pin_D3_high BSF STATUS,5 ; BANK 1 BCF TRISD,3 BCF STATUS,5 ; BANK 0 BSF PORTD,3 GOTO Finish_set_pin_high Set_pin_D4_high BSF STATUS,5 ; BANK 1 BCF TRISD,4 BCF STATUS,5 ; BANK 0 BSF PORTD,4 GOTO Finish_set_pin_high Set_pin_D5_high BSF STATUS,5 ; BANK 1 BCF TRISD,5 BCF STATUS,5 ; BANK 0 BSF PORTD,5 GOTO Finish_set_pin_high Set_pin_D6_high BSF STATUS,5 ; BANK 1 BCF TRISD,6 BCF STATUS,5 ; BANK 0 BSF PORTD,6 GOTO Finish_set_pin_high Set_pin_D7_high BSF STATUS,5 ; BANK 1 BCF TRISD,7 BCF STATUS,5 ; BANK 0 BSF PORTD,7 GOTO Finish_set_pin_high Set_pin_E0_high BSF STATUS,5 ; BANK 1 BCF TRISE,0 BCF STATUS,5 ; BANK 0 BSF PORTD,0 GOTO Finish_set_pin_high Finish_set_pin_high BCF PCLATH,3 BCF PCLATH,4 RETLW 01 ; Returns 01 in W since set pin high Pin_high_computed_GOTO BSF PCLATH,0 ; See page 30 of Microchip document DS39582B regarding BCF PCLATH,1 ; computed GOTO's that cross 256-byte memory boundaries. BCF PCLATH,2 ADDWF PCL,F ; Add W to program counter with upper 5 bits set to xx001 GOTO Set_pin_A0_high GOTO Set_pin_A1_high GOTO Set_pin_A2_high GOTO Set_pin_A3_high GOTO Set_pin_A4_high GOTO Set_pin_A5_high GOTO Finish_set_pin_high GOTO Finish_set_pin_high GOTO Set_pin_B0_high GOTO Finish_set_pin_high GOTO Finish_set_pin_high GOTO Finish_set_pin_high GOTO Finish_set_pin_high GOTO Set_pin_B5_high GOTO Finish_set_pin_high GOTO Finish_set_pin_high GOTO Set_pin_C0_high GOTO Set_pin_C1_high GOTO Set_pin_C2_high GOTO Set_pin_C3_high GOTO Set_pin_C4_high GOTO Set_pin_C5_high GOTO Set_pin_C6_high GOTO Set_pin_C7_high GOTO Set_pin_D0_high GOTO Set_pin_D1_high GOTO Set_pin_D2_high GOTO Set_pin_D3_high GOTO Set_pin_D4_high GOTO Set_pin_D5_high GOTO Set_pin_D6_high GOTO Set_pin_D7_high GOTO Set_pin_E0_high Set_pin_low MOVLW 28 SUBWF Port_and_pin,W ADDLW 0xDF BTFSC STATUS,0 GOTO Finish_set_pin_low ADDLW 21 GOTO Set_pin_low_computed_GOTO Set_pin_A0_low BSF STATUS,5 ; BANK 1 BCF TRISA,0 BCF STATUS,5 ; BANK 0 BCF PORTB,0 GOTO Finish_set_pin_low Set_pin_A1_low BSF STATUS,5 ; BANK 1 BCF TRISA,1 BCF STATUS,5 ; BANK 0 BCF PORTA,1 GOTO Finish_set_pin_low Set_pin_A2_low BSF STATUS,5 ; BANK 1 BCF TRISA,2 BCF STATUS,5 ; BANK 0 BCF PORTA,2 GOTO Finish_set_pin_low Set_pin_A3_low BSF STATUS,5 ; BANK 1 BCF TRISA,3 BCF STATUS,5 ; BANK 0 BCF PORTA,3 GOTO Finish_set_pin_low Set_pin_A4_low BSF STATUS,5 ; BANK 1 BCF TRISA,4 BCF STATUS,5 ; BANK 0 BCF PORTA,4 GOTO Finish_set_pin_low Set_pin_A5_low BSF STATUS,5 ; BANK 1 BCF TRISA,5 BCF STATUS,5 ; BANK 0 BCF PORTA,5 GOTO Finish_set_pin_low Set_pin_B0_low BSF STATUS,5 ; BANK 1 BCF TRISB,0 BCF STATUS,5 ; BANK 0 BCF PORTB,0 GOTO Finish_set_pin_low Set_pin_B5_low BSF STATUS,5 ; BANK 1 BCF TRISB,5 BCF STATUS,5 ; BANK 0 BCF PORTB,5 GOTO Finish_set_pin_low Set_pin_C0_low BCF TRISC_copy,0 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BCF PORTC,0 GOTO Finish_set_pin_low Set_pin_C1_low BCF TRISC_copy,1 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BCF PORTC,1 GOTO Finish_set_pin_low Set_pin_C2_low BCF TRISC_copy,2 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BCF PORTC,2 GOTO Finish_set_pin_low Set_pin_C3_low BCF TRISC_copy,3 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BCF PORTC,3 GOTO Finish_set_pin_low Set_pin_C4_low BCF TRISC_copy,4 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BCF PORTC,4 GOTO Finish_set_pin_low Set_pin_C5_low BCF TRISC_copy,5 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BCF PORTC,5 GOTO Finish_set_pin_low Set_pin_C6_low BCF TRISC_copy,6 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BCF PORTC,6 GOTO Finish_set_pin_low Set_pin_C7_low BCF TRISC_copy,7 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 BCF PORTC,7 GOTO Finish_set_pin_low Set_pin_D0_low BSF STATUS,5 ; BANK 1 BCF TRISD,0 BCF STATUS,5 ; BANK 0 BCF PORTD,0 GOTO Finish_set_pin_low Set_pin_D1_low BSF STATUS,5 ; BANK 1 BCF TRISD,1 BCF STATUS,5 ; BANK 0 BCF PORTD,1 GOTO Finish_set_pin_low Set_pin_D2_low BSF STATUS,5 ; BANK 1 BCF TRISD,2 BCF STATUS,5 ; BANK 0 BCF PORTD,2 GOTO Finish_set_pin_low Set_pin_D3_low BSF STATUS,5 ; BANK 1 BCF TRISD,3 BCF STATUS,5 ; BANK 0 BCF PORTD,3 GOTO Finish_set_pin_low Set_pin_D4_low BSF STATUS,5 ; BANK 1 BCF TRISD,4 BCF STATUS,5 ; BANK 0 BCF PORTD,4 GOTO Finish_set_pin_low Set_pin_D5_low BSF STATUS,5 ; BANK 1 BCF TRISD,5 BCF STATUS,5 ; BANK 0 BCF PORTD,5 GOTO Finish_set_pin_low Set_pin_D6_low BSF STATUS,5 ; BANK 1 BCF TRISD,6 BCF STATUS,5 ; BANK 0 BCF PORTD,6 GOTO Finish_set_pin_low Set_pin_D7_low BSF STATUS,5 ; BANK 1 BCF TRISD,7 BCF STATUS,5 ; BANK 0 BCF PORTD,7 GOTO Finish_set_pin_low Set_pin_E0_low BSF STATUS,5 ; BANK 1 BCF TRISE,0 BCF STATUS,5 ; BANK 0 BCF PORTE,0 GOTO Finish_set_pin_low Finish_set_pin_low RETLW 00 ; Return 00 since set pin low Set_pin_low_computed_GOTO BCF PCLATH,0 ; See page 30 of Microchip document DS39582B regarding BSF PCLATH,1 ; computed GOTO's that cross 256-byte memory boundaries. BCF PCLATH,2 ADDWF PCL,F ; Add W to program counter's least significant byte GOTO Set_pin_A0_low GOTO Set_pin_A1_low GOTO Set_pin_A2_low GOTO Set_pin_A3_low GOTO Set_pin_A4_low GOTO Set_pin_A5_low GOTO Finish_set_pin_low GOTO Finish_set_pin_low GOTO Set_pin_B0_low GOTO Finish_set_pin_low GOTO Finish_set_pin_low GOTO Finish_set_pin_low GOTO Finish_set_pin_low GOTO Set_pin_B5_low GOTO Finish_set_pin_low GOTO Finish_set_pin_low GOTO Set_pin_C0_low GOTO Set_pin_C1_low GOTO Set_pin_C2_low GOTO Set_pin_C3_low GOTO Set_pin_C4_low GOTO Set_pin_C5_low GOTO Set_pin_C6_low GOTO Set_pin_C7_low GOTO Set_pin_D0_low GOTO Set_pin_D1_low GOTO Set_pin_D2_low GOTO Set_pin_D3_low GOTO Set_pin_D4_low GOTO Set_pin_D5_low GOTO Set_pin_D6_low GOTO Set_pin_D7_low GOTO Set_pin_E0_low Read_pin MOVLW 28 ; Base of port/pin numbering. Port A, pin 0 is 0x28. Port E, pin 7 is 0x4F. SUBWF Port_and_pin,W ; W now has 0x00 for port A, pin 0 ADDLW 0xDD BTFSC STATUS,0 GOTO Finish_read_pin ADDLW 23 GOTO Read_pin_computed_GOTO Read_pin_A0 BSF STATUS,5 ; BANK 1 BSF TRISA,0 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTA,0 INCF Temp_5,F GOTO Finish_read_pin Read_pin_A1 BSF STATUS,5 ; BANK 1 BSF TRISA,1 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTA,1 INCF Temp_5,F GOTO Finish_read_pin Read_pin_A2 BSF STATUS,5 ; BANK 1 BSF TRISA,2 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTA,2 INCF Temp_5,F GOTO Finish_read_pin Read_pin_A3 BSF STATUS,5 ; BANK 1 BSF TRISA,3 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTA,3 INCF Temp_5,F GOTO Finish_read_pin Read_pin_A4 BSF STATUS,5 ; BANK 1 BSF TRISA,4 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTA,4 INCF Temp_5,F GOTO Finish_read_pin Read_pin_A5 BSF STATUS,5 ; BANK 1 BSF TRISA,5 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTA,5 INCF Temp_5,F GOTO Finish_read_pin Read_pin_B0 BSF STATUS,5 ; BANK 1 BSF TRISB,0 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTB,0 INCF Temp_5,F GOTO Finish_read_pin Read_pin_B4 BSF STATUS,5 ; BANK 1 BSF TRISB,4 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTB,4 INCF Temp_5,F GOTO Finish_read_pin Read_pin_B5 BSF STATUS,5 ; BANK 1 BSF TRISB,5 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTB,5 INCF Temp_5,F GOTO Finish_read_pin Read_pin_C0 BSF TRISC_copy,0 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTC,0 INCF Temp_5,F GOTO Finish_read_pin Read_pin_C1 BSF TRISC_copy,1 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTC,1 INCF Temp_5,F GOTO Finish_read_pin Read_pin_C2 BSF TRISC_copy,2 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTC,2 INCF Temp_5,F GOTO Finish_read_pin Read_pin_C3 BSF TRISC_copy,3 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTC,3 INCF Temp_5,F GOTO Finish_read_pin Read_pin_C4 BSF TRISC_copy,4 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTC,4 INCF Temp_5,F GOTO Finish_read_pin Read_pin_C5 BSF TRISC_copy,5 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTC,5 INCF Temp_5,F GOTO Finish_read_pin Read_pin_C6 BSF TRISC_copy,6 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTC,6 INCF Temp_5,F GOTO Finish_read_pin Read_pin_C7 BSF TRISC_copy,7 MOVF TRISC_copy,W BSF STATUS,5 ; BANK 1 MOVWF TRISC BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTC,7 INCF Temp_5,F GOTO Finish_read_pin Read_pin_D0 BSF STATUS,5 ; BANK 1 BSF TRISD,0 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTD,0 INCF Temp_5,F GOTO Finish_read_pin Read_pin_D1 BSF STATUS,5 ; BANK 1 BSF TRISD,1 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTD,1 INCF Temp_5,F GOTO Finish_read_pin Read_pin_D2 BSF STATUS,5 ; BANK 1 BSF TRISD,2 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTD,2 INCF Temp_5,F GOTO Finish_read_pin Read_pin_D3 BSF STATUS,5 ; BANK 1 BSF TRISD,3 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTD,3 INCF Temp_5,F GOTO Finish_read_pin Read_pin_D4 BSF STATUS,5 ; BANK 1 BSF TRISD,4 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTD,4 INCF Temp_5,F GOTO Finish_read_pin Read_pin_D5 BSF STATUS,5 ; BANK 1 BSF TRISD,5 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTD,5 INCF Temp_5,F GOTO Finish_read_pin Read_pin_D6 BSF STATUS,5 ; BANK 1 BSF TRISD,6 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTD,6 INCF Temp_5,F GOTO Finish_read_pin Read_pin_D7 BSF STATUS,5 ; BANK 1 BSF TRISD,7 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTD,7 INCF Temp_5,F GOTO Finish_read_pin Read_pin_E2 BSF STATUS,5 ; BANK 1 BSF TRISE,2 BCF STATUS,5 ; BANK 0 CLRF Temp_5 BTFSC PORTE,2 INCF Temp_5,F GOTO Finish_read_pin Finish_read_pin MOVF Temp_5,W MOVWF Returned_byte ; Returned_byte will be 01 if pin was low, 00 if low RETLW 00 ; Always returns with 00 in W Read_pin_computed_GOTO BSF PCLATH,0 ; See page 30 of Microchip document DS39582B regarding BSF PCLATH,1 ; computed GOTO's that cross 256-byte memory boundaries. BCF PCLATH,2 ADDWF PCL,F ; Add W to program counter and put in PC, PC now has address ; of GOTO Read_pin_A0 instruction that follows for W=0x00. GOTO Read_pin_A0 GOTO Read_pin_A1 GOTO Read_pin_A2 GOTO Read_pin_A3 GOTO Read_pin_A4 GOTO Read_pin_A5 GOTO Finish_read_pin GOTO Finish_read_pin GOTO Read_pin_B0 GOTO Finish_read_pin GOTO Finish_read_pin GOTO Finish_read_pin GOTO Read_pin_B4 GOTO Read_pin_B5 GOTO Finish_read_pin GOTO Finish_read_pin GOTO Read_pin_C0 GOTO Read_pin_C1 GOTO Read_pin_C2 GOTO Read_pin_C3 GOTO Read_pin_C4 GOTO Read_pin_C5 GOTO Read_pin_C6 GOTO Read_pin_C7 GOTO Read_pin_D0 GOTO Read_pin_D1 GOTO Read_pin_D2 GOTO Read_pin_D3 GOTO Read_pin_D4 GOTO Read_pin_D5 GOTO Read_pin_D6 GOTO Read_pin_D7 GOTO Finish_read_pin GOTO Finish_read_pin GOTO Read_pin_E2 ; Times that follow include time for MOVLW, MOVWF, and CALL ; If uS_to_wait holds 0x00, waits 0.2 nS * 12 ; If uS_to_wait holds 0x01, waits 0.2 nS * (11 + 4) ; If uS_to_wait holds 0x02, waits 0.2 nS * (11 + 5 + 4) ; If uS_to_wait holds t, waits 0.2 nS * [11 + 5*(t-1) + 4] = 2 + t uS Wait_uS MOVLW uS_to_wait ; 2 + microseconds MOVWF FSR ; Set indirect addressing base to uS_to_wait MOVF INDF,W ; Copy contents of uS_to_wait using indirect addressing BTFSC STATUS,2 ; Test zero bit, skip if not set GOTO Wait_uS_3 ; End if reg uS_to_wait has become zero GOTO Wait_uS_2 ; Keep waiting otherwise Wait_uS_1 NOP CLRWDT Wait_uS_2 DECFSZ INDF,F GOTO Wait_uS_1 Wait_uS_3 RETLW 00 ; Check for line short and presence pulse from sensor ; Pulse pin low for 482 uS ; Read pin after another 155 uS ; Read pin again after another 300 uS ; Delay 10 uS and then return Do_check_temp_sensor_presence MOVLW 63 ; Initialize Temp_sensor_status with 0x63 (99 decimal) that signifies MOVWF Temp_sensor_status ; sensor ok if returned. Later it may be changed to 0x02 or 0x08 CALL Read_pin ; Make sure pin is allowing pull-up resistor to pull line high. Send reset pulse of 480 uS CALL Set_pin_low ; Set pin low MOVLW 02 ; Make next delay loop happen twice so that with overhead MOVWF Loop_count ; the delay is .4 + 2*239 + 0.6 + 2.8 uS = 481.8 uS Do_check_temp_sensor_presence_1 MOVLW 0xED MOVWF uS_to_wait CALL Wait_uS DECFSZ Loop_count,F GOTO Do_check_temp_sensor_presence_1 CALL Read_pin ; Allow pin to go high (TRIS set to input 1.4 uS before end of call MOVLW 0x80 ; Delay 1.4+128*0.6 + 3*0.2 = 78.8 uS before looking for MOVWF Loop_counter_0 ; presence pulse from sensor(s) DECFSZ Loop_counter_0,F ; The above delay was found experimentally by setting the read in GOTO $-1 ; the middle of the combined presence pulses of 35 thermometers NOP NOP ; MOVLW 0x20 ; Sample presence pulse 32 times for precise location ; MOVWF Loop_count ;Test_1 ; CALL Read_pin ; 25 cycles * 0.2 = 5 uS ; MOVF Returned_byte,W ; MOVWF Byte_for_USB ; CALL Send_byte ; 28 cycles * 0.2 = 5.4 uS ; DECFSZ Loop_count,F ; Total of (11 + 25 + 28) *0.2 = 74*0.2 = 11 uS ; GOTO Test_1 ; CALL Send_immediate ; MOVLW 20 ; Special return code of 0x20 ; MOVWF Temp_sensor_status ; RETLW 00 CALL Read_pin ; 1st Read, looking for presence pulse MOVF Returned_byte,W MOVWF Pin_reading_1 MOVLW 02 MOVWF Loop_count ; Prepare to do next delay twice Do_check_temp_sensor_presence_2 MOVLW 93 ; Delay 147*2 + 28*0.6 = 310.8 uS MOVWF uS_to_wait CALL Wait_uS DECFSZ Loop_count,F GOTO Do_check_temp_sensor_presence_2 CALL Read_pin ; 2nd Read, if still low, line is shorted MOVF Returned_byte,W MOVWF Pin_reading_2 ; Pin reading saved in reg 30 MOVF Pin_reading_2,F BTFSS STATUS,2 ; 2nd reading was also low, line is shorted, skip to set status GOTO Do_check_temp_sensor_presence_3 MOVLW 08 ; Indicate short_circuit by returning an 8 in Temp_sensor_status MOVWF Temp_sensor_status GOTO Do_check_temp_sensor_presence_4 Do_check_temp_sensor_presence_3 DECFSZ Pin_reading_1,W ; 1st reading high indicates no sensor, DEC makes it zero, skip to report no sensor GOTO Do_check_temp_sensor_presence_4 ; 1st reading was low so all ok. MOVLW 02 ; Indicate line no sensor by returning a 2 in Temp_sensor_status MOVWF Temp_sensor_status Do_check_temp_sensor_presence_4 ; 1st reading was low and 2nd reading was high, so all ok MOVLW 10 ; Delay 1 + 0.2 * 3 * 16 = 10.6 uS before returning MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP RETLW 00 Send_bytes_and_bits_to_temp_sensor ; The bits to send are stored as byte array with base in W MOVWF FSR ; Set indirect addressing to point to the beginning of that byte array MOVF Nbr_of_bits_for_sensor,W MOVWF Nbr_bytes_for_sensor ; This will be the byte count after some shifting MOVWF Nbr_of_leftover_bits ; This will be nbr of bits remaining in the final byte MOVLW 07 ; Clear bits 3-7 in number of bits remaining ANDWF Nbr_of_leftover_bits,F RRF Nbr_bytes_for_sensor,F ; Divide by 8 to get byte count and clear bits 5-7 RRF Nbr_bytes_for_sensor,F RRF Nbr_bytes_for_sensor,F MOVLW 1F ANDWF Nbr_bytes_for_sensor,F BTFSC STATUS,2 ; See if byte count was zero, skip if not GOTO Send_bytes_and_bits_to_temp_sensor_2 Send_bytes_and_bits_to_temp_sensor_1 ; Send the bytes MOVF INDF,W MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor INCF FSR,F DECFSZ Nbr_bytes_for_sensor,F GOTO Send_bytes_and_bits_to_temp_sensor_1 Send_bytes_and_bits_to_temp_sensor_2 ; Send the remaining bits, if any MOVF Nbr_of_leftover_bits,W BTFSC STATUS,2 RETLW 00 ; Done since no remaining bits MOVWF Nbr_of_bits_to_send MOVF INDF,W MOVWF Byte_with_bits_for_sensor CALL Send_up_to_8_bits_to_temp_sensor RETLW 00 Send_byte_to_temp_sensor ; Send a byte to DS18S20 sensor MOVLW 08 MOVWF Nbr_of_bits_to_send Send_up_to_8_bits_to_temp_sensor MOVF Nbr_of_bits_to_send,F BTFSC STATUS,2 ; Skip if bit count is not 0 GOTO Send_up_to_8_bits_to_temp_sensor_3 MOVF Byte_with_bits_for_sensor,W ; Examine bit 0 of the byte ANDLW 01 MOVWF Temp_8 ; Save is temporarily NOP NOP CALL Set_pin_low ; Initiate a bit transmission with a sync pulse MOVLW 06 ; Delay (0x06 loops) 4 uS MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP MOVF Temp_8,F BTFSC STATUS,2 GOTO Send_up_to_8_bits_to_temp_sensor_1 NOP NOP CALL Read_pin ; Bit was 1, let line be pulled high by pull-up resistor GOTO Send_up_to_8_bits_to_temp_sensor_2 Send_up_to_8_bits_to_temp_sensor_1 ; Bit was 0, keep line low CALL Set_pin_low Send_up_to_8_bits_to_temp_sensor_2 MOVLW 6D ; Delay 66.4 uS - duration of low or high bit from master MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP NOP CALL Read_pin ; Let line be pulled high by pull-up resistor MOVLW 10 ; 10 uS delay - recovery time MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP BCF STATUS,0 RRF Byte_with_bits_for_sensor,F ; Byte with bits for next bit to be at 0 position DECF Nbr_of_bits_to_send,F GOTO Send_up_to_8_bits_to_temp_sensor ; Send next bit Send_up_to_8_bits_to_temp_sensor_3 MOVLW 10 ; 10 uS delay - extra recovery time (may not be necessary) MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP RETLW 00 Read_temp_sensor_bit_pair CLRF Byte_with_bits_from_sensor MOVLW 02 MOVWF Nbr_of_bits_to_read GOTO Read_temp_sensor_bits Read_temp_sensor_byte CLRF Byte_with_bits_from_sensor MOVLW 08 MOVWF Nbr_of_bits_to_read Read_temp_sensor_bits MOVF Nbr_of_bits_to_read,F ; (5 + 18)*0.2 = 4.6 uS until set low BTFSC STATUS,2 GOTO Read_temp_sensor_bits_2 ; Bit count is 0, so all done CALL Set_pin_low ; Send sync pulse, (4.0 uS before set low, 0.8 uS after) CALL Read_pin ; End sync pulse (4.0 uS before TRIS is set, 1.6 uS after) MOVLW 04 ; Delay 1.6+2*0.2+4*0.6+2*0.2+4.6=9.4 uS until pin is read MOVWF Loop_counter_0 ; So time between start of sync and reading is 14.6 uS DECFSZ Loop_counter_0,F GOTO $-1 CALL Read_pin ; Read pin (4.6 uS before READ, 2.0 uS after) MOVF Returned_byte,W ; (7*0.2+4*0.2+99*0.6+10*0.2+16*0.6+4*0.2+25*0.2=10.0+69.0= 79.0 uS until next sync MOVWF Temp_8 ; Temporarily save result MOVLW 63 ; Delay 99*0.6+5*0.2=60.4 uS MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP NOP BCF STATUS,0 RRF Byte_with_bits_from_sensor,F ; Rotate result byte right DECFSZ Temp_8,W GOTO Read_temp_sensor_bits_1 MOVLW 80 ; (Why not use BSF Byte_with_bits_from_sensor,7 here?) ADDWF Byte_with_bits_from_sensor,F ; Add 0x80 if bit was high Read_temp_sensor_bits_1 MOVLW 10 ; (0x10 loops) Delay 10 uS, additional delay after byte read - may not be necessary MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP DECF Nbr_of_bits_to_read,F GOTO Read_temp_sensor_bits ; Get next bit Read_temp_sensor_bits_2 MOVLW 10 ; Delay 10 uS MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 NOP BCF PCLATH,3 ; I don't think these are necessary here BCF PCLATH,4 ; All code is below 0x1FF RETLW 00 Get_bit_from_byte_array MOVLW 01 SUBWF Bit_index,W MOVWF ROM_array_byte ; This will be the byte index MOVWF ROM_array_byte_bit ; This will be bit index (0-7) within the byte MOVLW 07 ; Clear bits 3-7 in bit index ANDWF ROM_array_byte_bit,F RRF ROM_array_byte,F ; Divide by 8 to get byte count and clear bits 5-7 RRF ROM_array_byte,F RRF ROM_array_byte,F MOVLW 1F ANDWF ROM_array_byte,W ADDLW ROM_code MOVWF FSR ; Indirect addressing should now point to the correct byte MOVF ROM_array_byte_bit,W RLF ROM_array_byte_bit,F ADDWF ROM_array_byte_bit,W BCF PCLATH,0 ; Be careful that this computed GOTO does not cross a BCF PCLATH,1 ; 256-byte boundary. These bits in PCLATH specify that BSF PCLATH,2 ; these instructions are between 0400 and 04FF ADDWF PCL,F ; Add 3 times bit number to program counter BTFSC INDF,0 RETLW 01 RETLW 00 BTFSC INDF,1 RETLW 01 RETLW 00 BTFSC INDF,2 RETLW 01 RETLW 00 BTFSC INDF,3 RETLW 01 RETLW 00 BTFSC INDF,4 RETLW 01 RETLW 00 BTFSC INDF,5 RETLW 01 RETLW 00 BTFSC INDF,6 RETLW 01 RETLW 00 BTFSC INDF,7 RETLW 01 RETLW 00 Set_bit_in_byte_array MOVLW 01 SUBWF Bit_index,W MOVWF ROM_array_byte ; This will be the byte count MOVWF ROM_array_byte_bit ; and this will be the bit index in the byte MOVLW 07 ; Clear bits 3-7 in number of bits remaining ANDWF ROM_array_byte_bit,F RRF ROM_array_byte,F ; Divide by 8 to get the byte count and clear bits 5-7 RRF ROM_array_byte,F RRF ROM_array_byte,F MOVLW 1F ANDWF ROM_array_byte,W ADDLW ROM_code MOVWF FSR ; Indirect addressing should now point to the correct byte RLF ROM_array_byte_bit,W ; Carry flag should be zero from above operation BCF PCLATH,0 ; Be careful that this computed GOTO does not cross a BCF PCLATH,1 ; 256-byte boundary. These bits in PCLATH specify that BSF PCLATH,2 ; These instructions are between 0400 and 04FF ADDWF PCL,F ; Add 2 times bit number to program counter BSF INDF,0 RETURN BSF INDF,1 RETURN BSF INDF,2 RETURN BSF INDF,3 RETURN BSF INDF,4 RETURN BSF INDF,5 RETURN BSF INDF,6 RETURN BSF INDF,7 RETURN Clear_bit_in_byte_array MOVLW 01 SUBWF Bit_index,W MOVWF ROM_array_byte ; This will be byte count MOVWF ROM_array_byte_bit ; and to this will be the bit index in the byte MOVLW 07 ; Clear bits 3-7 in number of bits remaining ANDWF ROM_array_byte_bit,F RRF ROM_array_byte,F ; Divide by 8 to get byte count and clear bits 5-7 RRF ROM_array_byte,F RRF ROM_array_byte,F MOVLW 1F ANDWF ROM_array_byte,W ADDLW ROM_code MOVWF FSR ; Indirect addressing should now point to the byte RLF ROM_array_byte_bit,W BCF PCLATH,0 ; Be careful that this computed GOTO does not cross a BCF PCLATH,1 ; 256-byte boundary. These bits in 0A specify that BSF PCLATH,2 ; These instructions are between 0400 and 04FF ADDWF PCL,F ; Add 2 times bit number to program counter BCF INDF,0 RETURN BCF INDF,1 RETURN BCF INDF,2 RETURN BCF INDF,3 RETURN BCF INDF,4 RETURN BCF INDF,5 RETURN BCF INDF,6 RETURN BCF INDF,7 RETURN Init ; Chip and communications channel initialization CLRF FSR MOVLW 1F ANDWF STATUS,F ; Clear register bank select bits (upper 3 bits of STATUS) MOVLW 07 BSF STATUS,5 ; BANK 1 MOVWF ADCON1 ; Set ADCON1 for all digital inputs BCF STATUS,5 ; BANK 0 MOVWF ADCON0 ; Set ADCON0 for Fosc/2, Channel AN0, GO, A/D converter powered up BSF STATUS,5 ; BANK 1 MOVWF ADCON1 ; Set ADCON1 for all digital inputs BCF STATUS,5 ; BANK 0 MOVWF ADCON0 ; Set ADCON0 for Fosc/2, Channel AN0, GO, A/D converter powered up MOVLW 0xFF ; *** Must be unnecessary MOVWF TRISC_copy ; *** Must be unnecessary MOVLW 0xFF BSF STATUS,5 ; BANK 1 MOVWF TRISA ; Set TRISA for input MOVWF TRISB ; Set TRISB for input MOVWF TRISC ; Set TRISC for input BCF STATUS,5 ; BANK 0 MOVWF TRISC_copy ; Is this really necessary? BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set TRISD for input BSF TRISE,0 BSF TRISE,1 BSF TRISE,2 ; Set TRISE, pins 0, 1 and 2 for input MOVLW 86 MOVWF ADCON1 ; Set ADCON1 for right-justfied format, and all digital inputs BCF STATUS,5 ; BANK 0 MOVF ADCON0,W ANDLW 38 MOVWF ADCON0 ; Clear ADCON0 Fosc/2, GO, and ADON bits, but not channel selection bits ; Set handshake lines to FT2232C high BSF STATUS,5 ; BANK 1 BCF TRISB,2 ; Set TRISB, pin 2 (WR) for output BCF STATUS,5 ; BANK 0 BSF PORTB,2 ; Set PORTB, pin 2 (WR) high BSF STATUS,5 ; BANK 1 BCF TRISB,1 ; Set TRISB, pin 1 (RD#) for output BCF STATUS,5 ; BANK 0 BSF PORTB,1 ; Set PORTB, pin 1 (RD#) to high BSF STATUS,5 ; BANK 1 BCF TRISE,1 ; Set TRISE, pin 1 (SI/WUB) for output BCF STATUS,5 ; BANK 0 BSF PORTE,1 ; Set PORTE, pin 1 (SI/WUB) to high MOVLW 64 MOVWF mS_to_wait CALL Wait_mS ; Wait 100 mS and flush any byte in FT2232C buffer waiting to come to here BSF STATUS,5 ; BANK 1 BSF TRISB,4 ; Set TRISB, pin 4 (RXF#) for input BCF STATUS,5 ; BANK 0 BTFSC PORTB,4 ; Read PORTB, pin 4 (RXF#), skip if low GOTO Init_1 ; If RXF# is high, finish initialization. Otherwise BSF STATUS,5 ; BANK 1 BCF TRISB,1 ; Set TRISB, pin 1 (RD#) for output BCF STATUS,5 ; BANK 0 BCF PORTB,1 ; Set PORTB, pin 1 (RD#) to low BSF STATUS,5 ; BANK 1 BCF TRISB,1 ; Set TRISB, pin 1 (RD#) for output BCF STATUS,5 ; BANK 0 BSF PORTB,1 ; Set PORTB, pin 1 (RD#) to high Init_1 CLRF LED_flash_count Init_2 ; Flash LED quickly 9 times to signal unit is initialized MOVF LED_flash_count,W SUBLW 09 BTFSS STATUS,0 GOTO Process_command ; Done flashing, Go to command processing loop CLRWDT MOVLW 28 MOVWF mS_to_wait ; Wait 40 mS CALL Wait_mS BSF STATUS,5 ; BANK 1 BCF TRISE,0 ; Set TRISE, pin 0 for output BCF STATUS,5 ; BANK 0 BSF PORTE,0 ; Set PORTE, pin 0 to high (LED on) MOVLW 28 MOVWF mS_to_wait CALL Wait_mS ; Wait 40 mS BSF STATUS,5 ; BANK 1 BCF TRISE,0 ; Set TRISE, pin 0 for output BCF STATUS,5 ; BANK 0 BCF PORTE,0 ; Set PORTE, pin 0 to low (LED off) INCF LED_flash_count,F ; Increment flash count GOTO Init_2 Process_command ; Start of Command Processing Loop CLRWDT GOTO Toggle_LED ; Do toggle_led() (Actually only toggles it once in 60,000 visits) Process_command_1 BSF STATUS,5 ; BANK 1 BSF TRISB,4 ; Set TRISB, bit 4 for input BCF STATUS,5 ; BANK 0 BTFSC PORTB,4 ; Test if PORTB, pin 4 (RXF#) GOTO Continue_command_processing ; RXF# is high. Go to end of command loop GOTO Receive_command ; RXF# is low. Get command bytes from FT2232C Return_board_id ; Command 0xA7 - This must be the first command processed MOVF Command_byte_1,W ; because Receive_command comes back to here SUBLW 0xA7 BTFSS STATUS,2 GOTO Setup_AtoD MOVLW 0x44 MOVWF Byte_for_USB CALL Send_byte MOVLW 0x4C MOVWF Byte_for_USB CALL Send_byte MOVLW 0x50 MOVWF Byte_for_USB CALL Send_byte MOVLW 0x2D MOVWF Byte_for_USB CALL Send_byte MOVLW 0x4D MOVWF Byte_for_USB CALL Send_byte MOVLW 0x30 MOVWF Byte_for_USB CALL Send_byte CALL Send_immediate CLRF Command_byte_1 ; Clear Command byte to signify command completion GOTO Process_command Setup_AtoD ; Command 0xA8 MOVF Command_byte_1,W SUBLW 0xA8 BTFSS STATUS,2 GOTO Run_AtoD ; Not 0xA8 so try next command GOTO Do_setup_AtoD Finish_setup_AtoD CLRF Command_byte_1 GOTO Process_command Run_AtoD ; Command 0xA9 MOVF Command_byte_1,W SUBLW 0xA9 BTFSS STATUS,2 GOTO Set_pins ; Not 0xA9 so try next command GOTO Read_AtoD_burst Finish_run_AtoD CLRF Command_byte_1 GOTO Process_command Set_pins ; Command 0xA6 MOVF Command_byte_1,W SUBLW 0xA6 BTFSS STATUS,2 GOTO Read_pins ; Not 0xA6 so try next command MOVF Command_byte_3,F BTFSC STATUS,2 GOTO Set_pins_1 ; Go set bit low MOVF Command_byte_2,W MOVWF Port_and_pin CALL Set_pin_high GOTO Set_pins_2 Set_pins_1 MOVF Command_byte_2,W MOVWF Port_and_pin CALL Set_pin_low Set_pins_2 CLRF Command_byte_1 GOTO Process_command Read_pins ; Command 0xA5 MOVF Command_byte_1,W SUBLW 0xA5 BTFSS STATUS,2 GOTO Loopback ; Not 0xA5 so try next command MOVF Command_byte_2,W MOVWF Port_and_pin CALL Read_pin MOVF Returned_byte,W MOVWF Byte_for_USB CALL Send_byte CALL Send_immediate CLRF Command_byte_1 GOTO Process_command Loopback ; Command 0xAF MOVF Command_byte_1,W SUBLW 0xAF BTFSS STATUS,2 GOTO Read_EEPROM MOVF Command_byte_2,W MOVWF Byte_for_USB CALL Send_byte CALL Send_immediate CLRF Command_byte_1 GOTO Process_command Read_EEPROM ; Command 0xAA MOVF Command_byte_1,W SUBLW 0xAA BTFSS STATUS,2 GOTO Write_EEPROM ; Not 0xAA, so try next command MOVF Command_byte_2,W BSF STATUS,6 ; BANK 2 MOVWF EEADR ; Put address EEADR CLRF EEADRH ; Clear EEADRH BSF STATUS,5 ; BANK 3 BCF EECON1,7 ; Clear bit 7 (EEPGD, to access data memory) of EECON1 BSF EECON1,0 ; Set bit 0 (RD) of EECON1 BCF STATUS,5 ; BANK 2 MOVF EEDATA,W ; Copy EEDATA to W BCF STATUS,6 ; BANK 0 MOVWF Byte_for_USB CALL Send_byte CALL Send_immediate CLRF Command_byte_1 GOTO Process_command Write_EEPROM ; Command 0xAB, See page 38 of PIC16F87XA (Microchip Document DS39582B) MOVF Command_byte_1,W ; but wait after write to EEPROM is done by watching WR bit clear SUBLW 0xAB ; rather than using NOPs. BTFSS STATUS,2 GOTO Check_temp_sensor_presence_match ; Not 0xAB, so try next command MOVF Command_byte_2,W BSF STATUS,6 ; BANK 2 MOVWF EEADR ; Put address EEADR CLRF EEADRH ; Clear EEADRH BCF STATUS,6 ; BANK 0 MOVF Command_byte_3,W BSF STATUS,6 ; BANK 2 MOVWF EEDATA ; Put new EEPROM data in EEDATA BSF STATUS,5 ; BANK 3 BCF EECON1,7 ; Clear bit 7 (EEPGD, to access data memory) of EECON1 BSF EECON1,2 ; Set bit 2 (WREN, write enable) of EECON1 BCF STATUS,5 ; BANK 2 BCF STATUS,6 ; BANK 0 MOVF INTCON,W MOVWF Shared_temp ; Temporarily save INTCON BCF INTCON,7 ; Clear bit 7 (GIE, disable all interrupts) of INTCON BSF STATUS,5 ; BANK 1 BSF STATUS,6 ; BANK 3 MOVLW 55 MOVWF EECON2 ; Set EECON2 to 0x55 MOVLW 0xAA MOVWF EECON2 ; Set EECON2 to 0xAA BSF EECON1,1 ; Set bit 1 (WR) of EECON1 BTFSC EECON1,1 ; Wait for bit 1 (WR) of EECON1 to clear GOTO $-1 BCF EECON1,2 ; Clear bit 2 (WREN) of EECON1 MOVF Shared_temp,W BCF STATUS,5 ; BANK 2 BCF STATUS,6 ; BANK 0 IORWF INTCON,F ; Restore INTCON from saved value in Shared_temp CLRF Command_byte_1 GOTO Process_command Check_temp_sensor_presence_match ; Command 0xBC MOVF Command_byte_1,W SUBLW 0xBC BTFSS STATUS,2 GOTO Check_temp_sensor_presence ; Not 0xBC, so try next command MOVF Command_byte_2,W MOVWF Port_and_pin CALL Do_check_temp_sensor_presence MOVF Temp_sensor_status,W ; Check if reg Temp_sensor_status has 99 decimal SUBLW 62 ; by subtracting 98 from it. BTFSS STATUS,0 GOTO Check_temp_sensor_presence_match_1 ; Yup, go return it and to MATCH ROM MOVF Temp_sensor_status,W ; Nope, return Error message of 0x02 or 0x08 MOVWF Byte_for_USB CALL Send_byte ; Send byte GOTO Process_command Check_temp_sensor_presence_match_1 MOVLW 63 ; Return decimal 99 to signify sensor ok MOVWF Byte_for_USB CALL Send_byte MOVLW 0x55 ; Send MATCH ROM command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor MOVLW 40 ; 64 bits MOVWF Nbr_of_bits_for_sensor MOVLW Command_byte_3 CALL Send_bytes_and_bits_to_temp_sensor MOVLW 44 ; Send CONVERT T command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor CLRF Command_byte_1 GOTO Process_command Check_temp_sensor_presence ; Command 0xAC MOVF Command_byte_1,W SUBLW 0xAC BTFSS STATUS,2 GOTO Read_temp_match ; Not 0xAC, so try next command MOVF Command_byte_2,W MOVWF Port_and_pin CALL Do_check_temp_sensor_presence MOVF Temp_sensor_status,W ; Check if reg Temp_sensor_status still has 99 decimal SUBLW 62 ; by subtracting 98 from it. BTFSS STATUS,0 GOTO Check_temp_sensor_presence_1 ; Yup, go return it and start conversion MOVF Temp_sensor_status,W ; Error message of 2 or 8 MOVWF Byte_for_USB CALL Send_byte ; Send byte GOTO Process_command Check_temp_sensor_presence_1 MOVLW 63 ; Return decimal 99 to signify sensor ok MOVWF Byte_for_USB CALL Send_byte MOVLW 0xCC ; Send SKIP ROM command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor MOVLW 44 ; Send CONVERT T command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor CLRF Command_byte_1 GOTO Process_command Read_temp_match ; Command 0xBD MOVF Command_byte_1,W SUBLW 0xBD BTFSS STATUS,2 GOTO Read_temp ; Not 0xBD, so try next command MOVF Command_byte_2,W MOVWF Port_and_pin CALL Do_check_temp_sensor_presence MOVLW 0x55 ; Send MATCH ROM command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor MOVLW 40 MOVWF Nbr_of_bits_for_sensor MOVLW Command_byte_3 CALL Send_bytes_and_bits_to_temp_sensor MOVLW 0xBE ; Send READ SCRATCHPAD command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor MOVLW 08 ; Delay about 7 uS including overhead MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 CLRF ROM_byte_count ; Clear bytes received count Read_temp_match_1 MOVF ROM_byte_count,W ; See if 9 bytes have been received SUBLW 08 BTFSS STATUS,0 GOTO Read_temp_match_2 ; Yup, finish up CALL Read_temp_sensor_byte MOVF Byte_with_bits_from_sensor,W MOVWF Byte_for_USB CALL Send_byte ; Send byte INCF ROM_byte_count,F GOTO Read_temp_match_1 ; Get next byte Read_temp_match_2 CALL Send_immediate CLRF Command_byte_1 GOTO Process_command Read_temp ; Command 0xAD MOVF Command_byte_1,W SUBLW 0xAD BTFSS STATUS,2 GOTO Read_temp_sensor_ROM ; Not 0xAD, so try next command MOVF Command_byte_2,W MOVWF Port_and_pin CALL Do_check_temp_sensor_presence MOVLW 0xCC ; Send SKIP ROM command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor MOVLW 0xBE ; Send READ SCRATCHPAD command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor MOVLW 08 ; Delay about 7 uS including overhead MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 CLRF Byte_count ; Clear bytes received count Read_temp_1 MOVF Byte_count,W ; See if 9 bytes have been received SUBLW 08 BTFSS STATUS,0 GOTO Read_temp_2 ; Yup, so finish up CALL Read_temp_sensor_byte MOVF Byte_with_bits_from_sensor,W MOVWF Byte_for_USB CALL Send_byte INCF Byte_count,F GOTO Read_temp_1 Read_temp_2 CALL Send_immediate CLRF Command_byte_1 GOTO Process_command Read_temp_sensor_ROM ; Command 0xBA MOVF Command_byte_1,W SUBLW 0xBA BTFSS STATUS,2 GOTO Search_temp_sensors ; Not 0xBA, so try next command MOVF Command_byte_2,W MOVWF Port_and_pin CLRF Byte_count ; Clear bytes received count CALL Do_check_temp_sensor_presence MOVLW 0x33 ; Send SKIP ROM command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor MOVLW 08 ; Delay about 7 uS including overhead MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 Read_temp_sensor_ROM_1 MOVF Byte_count,W ; See if 8 bytes have been received SUBLW 07 BTFSS STATUS,0 GOTO Read_temp_sensor_ROM_2 ; Finish up CALL Read_temp_sensor_byte MOVF Byte_with_bits_from_sensor,W MOVWF Byte_for_USB CALL Send_byte ; Send byte INCF Byte_count,F GOTO Read_temp_sensor_ROM_1 ; Get next byte Read_temp_sensor_ROM_2 CALL Send_immediate CLRF Command_byte_1 GOTO Process_command Search_temp_sensors ; Command 0xBB - See Dallas Semiconductor Maxim MOVF Command_byte_1,W ; i-Button Standard (doc 081297, Section C.3) SUBLW 0xBB BTFSS STATUS,2 GOTO Initialize_mavica ; Not 0xBB, so try next command CLRF Last_discrepancy MOVF Command_byte_2,W MOVWF Port_and_pin Search_temp_sensors_1 CALL Do_check_temp_sensor_presence MOVLW 63 SUBWF Temp_sensor_status,W BTFSS STATUS,2 GOTO Search_temp_sensors_12 ; Sensor not present or line shorted, go send 8 copies of error byte MOVLW 01 MOVWF Bit_index CLRF Discrepancy_marker MOVLW 0xF0 ; Send SEARCH ROM command MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor MOVLW 08 ; Delay about 7 uS including overhead MOVWF Loop_counter_0 DECFSZ Loop_counter_0,F GOTO $-1 Search_temp_sensors_2 CALL Read_temp_sensor_bit_pair ; Get bits A and B MOVLW 0xC0 SUBWF Byte_with_bits_from_sensor,W BTFSC STATUS,2 ; Skip if bits A and B are not both 1 GOTO Search_temp_sensors_13 ; A=B=1 should never happen, return 9 copies of Byte_with_bits_from_sensor MOVF Byte_with_bits_from_sensor,F BTFSC STATUS,2 ; Skip if bits A and C are not both 0 GOTO Search_temp_sensors_8 ; Both bits are 0, handle discrepancy BTFSS Byte_with_bits_from_sensor,6 ; Test if A is set, skip if not GOTO Search_temp_sensors_3 CALL Set_bit_in_byte_array ; Set bit in ROM array at Bit_index GOTO Search_temp_sensors_4 Search_temp_sensors_3 CALL Clear_bit_in_byte_array ; Clear bit in ROM array at Bit_index Search_temp_sensors_4 CALL Get_bit_from_byte_array ; Get bit from ROM array and send it to sensor MOVWF Byte_with_bits_for_sensor MOVLW 01 MOVWF Nbr_of_bits_to_send CALL Send_up_to_8_bits_to_temp_sensor INCF Bit_index,F ; Point to next bit, end this pass if bit 63 has been processed MOVF Bit_index,W SUBLW 41 BTFSS STATUS,2 GOTO Search_temp_sensors_2 ; Process next bit in this pass MOVLW ROM_code ; Done with this pass. Send the 8 ROM bytes to USB bus MOVWF FSR MOVLW 08 MOVWF Temp_9 Search_temp_sensors_5 MOVF INDF,W MOVWF Byte_for_USB CALL Send_byte INCF FSR,F DECFSZ Temp_9,F GOTO Search_temp_sensors_5 MOVLW 0xB4 ; Send READ POWER SUPPLY command for this sensor MOVWF Byte_with_bits_for_sensor CALL Send_byte_to_temp_sensor CLRF Byte_with_bits_from_sensor MOVLW 01 MOVWF Nbr_of_bits_to_read CALL Read_temp_sensor_bits ; Returned byte is 0 if on parasitic supply, 1 if external power MOVF Byte_with_bits_from_sensor,W MOVWF Byte_for_USB ; Send it the byte CALL Send_byte CALL Send_immediate MOVF Discrepancy_marker,W ; Update Last_discrepancy to value of Discrepancy_marker MOVWF Last_discrepancy BTFSC STATUS,2 ; Check if Last_discrepancy = 0 (unchanged) GOTO Search_temp_sensors_6 ; Finish if so GOTO Search_temp_sensors_1 ; Do another pass if not Search_temp_sensors_6 MOVLW 00 ; Prepare to send 9 null bytes to signify end of list MOVWF Byte_for_USB MOVLW 09 MOVWF Temp_9 Search_temp_sensors_7 ; Send W copies of Byte_for_USB CALL Send_byte DECFSZ Temp_9,F GOTO Search_temp_sensors_7 CALL Send_immediate CLRF Command_byte_1 GOTO Process_command Search_temp_sensors_8 ; Both test bits were zero MOVF Bit_index,W ; See if Bit_index = Last_discrepancy SUBWF Last_discrepancy,W BTFSC STATUS,2 GOTO Search_temp_sensors_10 ; Yes, so go set the bit in the ROM array MOVF Bit_index,W ; No, so see if Bit_index > Last_discrepancy SUBWF Last_discrepancy,W BTFSS STATUS,0 GOTO Search_temp_sensors_11 ; Yes, so go clear the bit in the ROM array CALL Get_bit_from_byte_array ; No, so see if ROM array bit is 1 SUBLW 00 BTFSS STATUS,2 GOTO Search_temp_sensors_4 ; It is a 0, so continue checking bits Search_temp_sensors_9 ; ROM array bit is a 1, so reset Discrepancy_marker to Bit_index MOVF Bit_index,W MOVWF Discrepancy_marker GOTO Search_temp_sensors_4 ; Now continue checking bits Search_temp_sensors_10 ; Set bit in ROM array at Bit_index CALL Set_bit_in_byte_array GOTO Search_temp_sensors_4 ; Continue checking bits Search_temp_sensors_11 ; Clear bit in ROM array at Bit_index CALL Clear_bit_in_byte_array GOTO Search_temp_sensors_9 ; Continue checking bits Search_temp_sensors_12 MOVF Temp_sensor_status,W ; Prepare to send 9 copies of Temp_sensor_status to signify error MOVWF Byte_for_USB MOVLW 09 MOVWF Temp_9 GOTO Search_temp_sensors_7 Search_temp_sensors_13 ; Send 9 copies of test result (0xC0) to signify A=B=1 error MOVF Byte_with_bits_from_sensor,W MOVWF Byte_for_USB MOVLW 09 MOVWF Temp_9 GOTO Search_temp_sensors_7 Initialize_mavica MOVF Command_byte_1,W SUBLW 0xC0 BTFSS STATUS,2 GOTO Read_mavica_bytes ; Not 0xC0, so try next command CALL Set_mavica_pin_low ; Pull pin low to start camera MOVLW 0x60 ; Waiting 96 mS MOVWF mS_to_wait CALL Wait_mS CALL Read_mavica_pin ; Allow pin to go high CLRF Loops_per_bit ; Now to calibrate Loops_per_bit CALL Wait_for_1st_sync_bit Initialize_mavica_1 CALL Read_mavica_pin ; Count while Waiting to go high INCF Loops_per_bit,F ; Read_mavica_pin takes 1.6 uS so loop is 3.0 uS IORLW 00 ; Sets zero flag if W is 0 BTFSC STATUS,2 GOTO Initialize_mavica_1 Initialize_mavica_2 CALL Read_mavica_pin ; Count While Waiting to go low again INCF Loops_per_bit,F IORLW 00 BTFSS STATUS,2 GOTO Initialize_mavica_2 MOVF Loops_per_bit,W MOVWF Byte_for_USB CALL Send_byte CALL Send_immediate MOVLW 23 ; Test code MOVWF Loops_per_bit ; Test code MOVLW 0x05 MOVWF Camera_handshake ; Counts ea/e2 occurrences in byte 3 CLRF Remote_handshake CLRF Command_byte_1 GOTO Process_command Wait_for_1st_sync_bit CLRF Temp_1 Wait_for_1st_sync_bit_1 INCF Temp_1,F NOP ; These NOPs are needed to make the loop take 17*0.2+1.6 = 5.0 uS NOP ; long high must therefore be at least 256*5.0=1280.0 uS NOP NOP NOP BTFSS STATUS,2 ; See if looped 256 times GOTO Wait_for_1st_sync_bit_2 ; No, to check pin GOTO Wait_for_sync_bit ; Timeout, return since in must be in long high Wait_for_1st_sync_bit_2 CALL Read_mavica_pin IORLW 00 BTFSC STATUS,2 GOTO Wait_for_1st_sync_bit ; It went to low before timeout. Start over. GOTO Wait_for_1st_sync_bit_1 ; Keep checking Wait_for_sync_bit ; Wait for long high to end CALL Read_mavica_pin IORLW 00 BTFSS STATUS,2 GOTO Wait_for_sync_bit RETURN Set_mavica_pin_low ; This code requires 8*0.2 = 1.6 uS BSF STATUS,5 ; BANK 1 BCF TRISA,0 BCF STATUS,5 ; BANK 0 BCF PORTA,0 NOP NOP RETURN Read_mavica_pin ; This code requires 8*0.2 = 1.6 uS for either result BSF STATUS,5 ; BANK 1 BSF TRISA,0 BCF STATUS,5 ; BANK 0 BTFSC PORTA,0 GOTO Read_mavica_pin_1 NOP RETLW 00 Read_mavica_pin_1 RETLW 01 Read_mavica_byte ; Wait for middle of 1st data bit BCF STATUS,0 RRF Loops_per_bit,W BCF STATUS,0 ADDWF Loops_per_bit,W MOVWF Loop_count MOVLW 0x08 ; Prepare to read 8 bits MOVWF Nbr_of_bits_to_read CLRF Byte_with_bits_from_sensor GOTO Read_mavica_byte_2 Read_mavica_byte_1 ; Wait for middle of next data bit BCF STATUS,0 RLF Byte_with_bits_from_sensor,F MOVF Loops_per_bit,W MOVWF Loop_count Read_mavica_byte_2 ; Read data bit and collect NOP NOP CALL Read_mavica_pin DECFSZ Loop_count,F GOTO Read_mavica_byte_2 ADDWF Byte_with_bits_from_sensor,F DECFSZ Nbr_of_bits_to_read,F ; See if finished with 8 data bits GOTO Read_mavica_byte_1 ; No, so get next bit RETURN Read_mavica_bytes MOVF Command_byte_1,W SUBLW 0xC1 BTFSS STATUS,2 GOTO Send_mavica_bytes ; Not 0xC1, so try next command Read_mavica_bytes_0 MOVLW 0x08 Read_mavica_bytes_1 MOVWF Byte_count CALL Wait_for_1st_sync_bit Read_mavica_bytes_2 CALL Read_mavica_byte COMF Byte_with_bits_from_sensor,W ; Send complement of byte MOVWF Byte_for_USB CALL Send_byte DECFSZ Byte_count,F GOTO Read_mavica_bytes_4 ; Position for reading next byte CALL Send_immediate CLRWDT DECFSZ Command_byte_2,F GOTO Read_mavica_bytes_3 CLRF Command_byte_1 GOTO Process_command Read_mavica_bytes_3 BTFSC Command_byte_1,0 GOTO Read_mavica_bytes_0 GOTO Send_mavica_bytes_0 Read_mavica_bytes_4 CALL Delay_bit_width Read_mavica_bytes_5 CALL Wait_for_sync_bit GOTO Read_mavica_bytes_2 Delay_bit_width ; Delay Loops_per_bit*5uS for Loops_per_bit > 2 BCF STATUS,0 MOVF Loops_per_bit,W ; (3n-2-1) uS + 15*.2 uS = 3n uS MOVWF Loop_count RLF Loop_count,F ADDWF Loop_count,F DECF Loop_count,F DECF Loop_count,F Delay_bit_width_1 ; 1 uS per loop NOP Delay_bit_width_2 NOP DECFSZ Loop_count,F GOTO Delay_bit_width_1 RETURN Delay_bit_width_less_10_cycles BCF STATUS,0 DECF Loops_per_bit,W ; [3(n-1)-1-1] uS + 15*.2 us = 3n-5+15*.2 uS = 3n - 2 uS MOVWF Loop_count RLF Loop_count,F ADDWF Loop_count,F DECF Loop_count,F GOTO Delay_bit_width_1 Send_mavica_byte ; Sending the command byte MOVLW 0x08 MOVWF Bit_index CALL Delay_bit_width ; Position at first data bit Send_mavica_byte_1 BTFSC Byte_with_bits_for_sensor,7 GOTO Send_mavica_byte_2 ; Go send a 1 bit CALL Read_mavica_pin ; Send a 0 bit GOTO Send_mavica_byte_3 Send_mavica_byte_2 CALL Set_mavica_pin_low ; Send a 1 bit Send_mavica_byte_3 CALL Delay_bit_width_less_10_cycles RLF Byte_with_bits_for_sensor,F DECFSZ Bit_index,F GOTO Send_mavica_byte_1 CALL Read_mavica_pin ; Make sure pin ends up high RETURN Send_mavica_bytes MOVF Command_byte_1,W SUBLW 0xC2 BTFSS STATUS,2 GOTO Read_port_C ; Not 0xC2, so try next command Send_mavica_bytes_0 MOVLW 0x70 ; Send 0x78 if command is non-zero, otherwise send 0x70 MOVF Command_byte_3,F BTFSS STATUS,2 MOVLW 0x78 MOVWF Byte_with_bits_for_sensor CALL Wait_for_1st_sync_bit CALL Send_mavica_byte MOVF Command_byte_3,W MOVWF Byte_with_bits_for_sensor CALL Wait_for_sync_bit CALL Send_mavica_byte MOVF Camera_handshake,F BTFSS STATUS,2 GOTO Send_mavica_bytes_3 ; Bypass remote handshaking this time BTFSC Remote_handshake,0 GOTO Send_mavica_bytes_1 MOVLW 0xC2 ; Remote_handshake == 0 MOVWF Byte_with_bits_for_sensor CALL Wait_for_sync_bit CALL Send_mavica_byte BSF Remote_handshake,0 ; Set Remote_handshake to 1 BCF Remote_handshake,1 GOTO Send_mavica_bytes_4 Send_mavica_bytes_1 ; Remote_handshake == 1 or 3 BTFSC Remote_handshake,1 GOTO Send_mavica_bytes_2 MOVLW 0xCA MOVWF Byte_with_bits_for_sensor CALL Wait_for_sync_bit CALL Send_mavica_byte BSF Remote_handshake,1 ; Set Remote_handshake to 3 GOTO Send_mavica_bytes_4 Send_mavica_bytes_2 ; Remote_handshake == 3 MOVLW 0xCA MOVWF Byte_with_bits_for_sensor CALL Wait_for_sync_bit CALL Send_mavica_byte CLRF Remote_handshake ; Set Remote_handshake to 0 MOVLW 0x05 MOVWF Camera_handshake GOTO Send_mavica_bytes_4 Send_mavica_bytes_3 ; Allow remaining bits to be high (0) CALL Wait_for_sync_bit ; and wait for next sync bit CALL Read_mavica_byte ; Get the 3rd byte and update Camera_handshake if needed MOVLW 0xE0 ANDWF Byte_with_bits_from_sensor,F XORWF Byte_with_bits_from_sensor,F BTFSS STATUS,2 GOTO Send_mavica_bytes_4 DECF Camera_handshake,F Send_mavica_bytes_4 MOVLW 0x05 MOVWF Byte_count GOTO Read_mavica_bytes_5 ; Go read the remaining 5 bytes and end Read_port_C ; Command 0x59 MOVF Command_byte_1,W SUBLW 59 BTFSS STATUS,2 GOTO Write_port_C ; Not 0x59, so try next command MOVLW 0xFF MOVWF TRISC_copy ; I wonder why this is necessary for Port C? GOTO Read_port_burst Write_port_C ; Command 0x5A MOVF Command_byte_1,W SUBLW 5A BTFSS STATUS,2 GOTO Read_port_A ; Not 0x5A, so try next command MOVLW 00 MOVWF TRISC_copy ; Necessary?? BSF STATUS,5 ; BANK 1 MOVWF TRISC ; Set TRISC for output BCF STATUS,5 ; BANK 0 MOVF Command_byte_2,W MOVWF PORTC ; Set byte on PORTC CLRF Command_byte_1 GOTO Process_command Read_port_A ; Command 0x55 MOVF Command_byte_1,W SUBLW 55 BTFSS STATUS,2 GOTO Write_port_A ; Not 0x55, so try next command GOTO Read_port_burst Write_port_A ; Command 0x56 MOVF Command_byte_1,W SUBLW 56 BTFSS STATUS,2 GOTO Read_port_D ; Not 0x56, so try next command MOVLW 00 BSF STATUS,5 ; BANK 1 MOVWF TRISA ; Set PORTA for output BCF STATUS,5 ; BANK 0 MOVF Command_byte_2,W MOVWF PORTA ; Set byte on PORTA CLRF Command_byte_1 GOTO Process_command Read_port_D ; Command 0x5B MOVF Command_byte_1,W SUBLW 5B BTFSS STATUS,2 GOTO Write_port_D ; Not 0x5B, so try next command GOTO Read_port_burst Write_port_D ; Command 0x5C MOVF Command_byte_1,W SUBLW 5C BTFSS STATUS,2 GOTO Continue_command_processing MOVLW 00 BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set PORTD for output BCF STATUS,5 ; BANK 0 MOVF Command_byte_2,W MOVWF PORTD ; Set byte on PORTD CLRF Command_byte_1 GOTO Process_command Continue_command_processing GOTO Process_command ; Start of block Port Read Processing ; 4 uS/measurement if block_count=2, block_size=0 (256), and delay=0 ; delay is in microseconds ; Port A = 0X55=0x01010101, Port C = 0X59=0x01011001, and Port D = 0X5B=0x01011011 Read_port_burst MOVLW 06 ; Initialize block reading variables ANDWF Command_byte_1,F ; Keep only bits 1 and 2 of read port command MOVF Command_byte_3,W MOVWF Command_byte_5 ; Use Command_byte_5 for counting measurements withing a block MOVLW 0xFF BTFSC Command_byte_1,1 ; If bit 1 of Command_byte_1 is set, must be port D GOTO Read_port_burst_3 ; Go prepare for port D measurement BTFSS Command_byte_1,2 ; else if bit 1 = 0, but bit 2 = 1, must be port A GOTO Read_port_burst_1 ; Go prepare for port C measurement BSF STATUS,5 ; BANK 1 Do this for port A MOVWF TRISA ; Set TRISA for all input GOTO Read_port_burst_2 Read_port_burst_1 ; Do this for port C BSF STATUS,5 ; BANK 1 MOVWF TRISC ; Set TRISC for all input Read_port_burst_2 ; Do this for ports A and C MOVLW 00 MOVWF TRISD ; Set TRISD for all output Read_port_burst_3 ; Do this for Ports A, C, and D BSF TRISE,2 ; Set TRISE, pin 2 (TXE#) for input BCF TRISB,2 ; Set TRISB, pin 2 for output BCF STATUS,5 ; BANK 0 Read_port_burst_4 ; Make a measurement BTFSC Command_byte_1,1 ; Check bit 1 of command GOTO Read_port_burst_6 ; Make port D measurement BTFSS Command_byte_1,2 ; Check bit 2 of command GOTO Read_port_burst_5 ; Make Port C measurement MOVF PORTA,W ; Read PORTA NOP ; Balance timing for Ports A and C GOTO Read_port_burst_7 ; Go send byte Read_port_burst_5 MOVF PORTC,W ; Read PORTC GOTO Read_port_burst_7 ; Go send byte Read_port_burst_6 MOVLW 0xFF BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set TRISD for all input BCF STATUS,5 ; BANK 0 MOVF PORTD,W ; Read PORTD MOVWF Temp_1 ; Temporarily save reading BSF STATUS,5 ; BANK 1 MOVLW 00 MOVWF TRISD ; Set TRISD for all output BCF STATUS,5 ; BANK 0 MOVF Temp_1,W ; Restore reading to W Read_port_burst_7 ; Wait for FT2232C to be ready BTFSC PORTE,2 ; Test PORTE, bit 2 (TXE#) for low GOTO $-1 ; Keep waiting for TXE# to go low MOVWF PORTD ; Set PORTD to value in W BCF PORTB,2 ; Clear PORTB, pin 2 (WR to low) telling FT2232C that valid data on lines BSF PORTB,2 ; Set PORTB, pin 2 (WR to high again) MOVF Command_byte_4,W ; Copy delay value to W BTFSC STATUS,2 GOTO Read_port_burst_9 ; Skip delay loop if delay is zero MOVWF Loop_counter_0 Read_port_burst_8 CLRWDT ; These delay 400 nS and clear watchdog timer CLRWDT DECFSZ Loop_counter_0,F GOTO Read_port_burst_8 ; Delay some more NOP ; Make delay=n be n uS greater than delay=0 Read_port_burst_9 DECFSZ Command_byte_5,F ; Decrement block size GOTO Read_port_burst_4 ; Do next measurement CLRWDT MOVF Command_byte_3,W MOVWF Command_byte_5 ; Reload Command_byte_5 as measurement counter DECFSZ Command_byte_2,F ; Decrement block_count, skip if zero GOTO Read_port_burst_4 ; Do next measurement MOVLW 0xFF BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set TRISD for all input BCF STATUS,5 ; BANK 0 GOTO Process_command ; Start of 0xA9 Run A/D Processing ; 24.0 uS/measurement if block_count=2, block_size=0 (256), and delay=0 Read_AtoD_burst ; delay units are microseconds MOVLW 00 BSF STATUS,5 ; BANK 1 MOVWF TRISD ; Set TRISD to all output BSF TRISE,2 ; Set TRISE, pin 2 (TXE#) for input BCF TRISB,2 ; Set TRISB, pin 2 for output BCF STATUS,5 ; BANK 0 MOVF Command_byte_4,W MOVWF Command_byte_6 ; Use Command_byte_6 for counting measurements within a block RLF Command_byte_2,W MOVWF Shared_temp RLF Shared_temp,F RLF Shared_temp,F MOVLW 0xF8 ANDWF Shared_temp,F MOVF ADCON0,W ANDLW 0xC7 IORWF Shared_temp,W MOVWF ADCON0 ; Put appropriate values in ADCON0 for specified analog port CLRWDT BCF PCLATH,3 ; These may not be necessary BCF PCLATH,4 Read_AtoD_burst_1 BSF ADCON0,2 ; Set ADCON0, bit 2 (GO/DONE#) starting first measurement BTFSC ADCON0,2 ; Test ADCON0, bit 2 (GO/DONE#), skip if clear GOTO $-1 ; Keep testing until clears MOVF ADRESL,W MOVWF Temp_1 ; Temporarily save ADRESL (A/D Result low) BSF STATUS,5 ; BANK 1 MOVF ADRESH,W ; Copy ADRESH (A/D Result High) to W BCF STATUS,5 ; BANK 0 BTFSC PORTE,2 ; Test PORTE, bit 2 (TXE#) for low GOTO $-1 ; Keep waiting for TXE# to go low MOVWF PORTD ; Set PORTD to value in W (ADRESH) BCF PORTB,2 ; Clear PORTB, pin 2 (WR to low signifying valid data on lines) BSF PORTB,2 ; Set PORTB, pin 2 (WR to high again) MOVF Temp_1,W ; Copy saved ADRESL (A/D Result Low) value to W BTFSC PORTE,2 ; Test PORTE, bit 2 (TXE#) for low GOTO $-1 ; Keep waiting for TXE# to go low MOVWF PORTD ; Set PORTD to value in W (ADRESL) BCF PORTB,2 ; Clear PORTB, pin 2 (WR to low signifying valid data on lines) BSF PORTB,2 ; Set PORTB, pin 2 (WR to high again) MOVF Command_byte_5,W ; Copy delay to W BTFSC STATUS,2 GOTO Read_AtoD_burst_3 ; Skip delay loop if delay is zero MOVWF Loop_counter_0 Read_AtoD_burst_2 CLRWDT ; Delay 400 nS while clearing watchdog timer CLRWDT DECFSZ Loop_counter_0,F GOTO Read_AtoD_burst_2 ; Delay some more NOP ; Make delay=n be n uS greater than delay=0 Read_AtoD_burst_3 DECFSZ Command_byte_6,F ; Decrement reading count, skip if zero GOTO Read_AtoD_burst_1 ; Get next measurement CLRWDT MOVF Command_byte_4,W ; Reload reading count to W with block_size MOVWF Command_byte_6 DECFSZ Command_byte_3,F ; Decrement block_count and skip if zero GOTO Read_AtoD_burst_1 ; Get next measurement CLRF Command_byte_1 GOTO Process_command END