Login
Logout>
Overview
Firmware
Hardware
Purchase
FAQ
Contact
Sign Up
Device Firmware


Trinfactor III uses PIC 16F677 microcontroller. This page lists the firmware written for Trinfactor. The firmware was written in PIC assembly and I2C application example in PIC 16F website was referenced. In a nutshell, the device uses timer, analog-digital converter, and I2C slave-module in PIC 16F677 uC. There are two LEDs in the device to indicate when the device is turned on and when the battery level fall below 3.2V. Third output turns off the signal to the NFET that controls the power supplied to the sensors. The NFET can be controlled by data sent through the NXT. We will soon post the VI written for NXT. Please check back in few weeks.
Please feel free to use the firmware in any way you want. If you have any questions or comments please check the FAQ section, or the contact page. We will try our best to answer you.
#### Author: Binay Poudel binay150@yahoo.com Robot Study Team Trinity College
  #include    <p16f677.inc>    ; processor specific variable definitions
__CONFIG _MCLRE_OFF &_INTRC_OSC_NOCLKOUT &_WDT_OFF

#define slave_add b'10001000'
#define RX_BUF_LEN 8
#define sensor_off b'10001000'
#define sensor_on b'11001000'

udata
    on_off res 1
    Temp res 1
    state_check res 1
    see res 1
    seconds res 1
    battery_level res 1
    Index res 1
    ADCindex res 1
    ADCcount res 1
    RXBuffer res RX_BUF_LEN
;------------------------------------------------------------------------------------------------
org 0x00
goto Start
org 0x04 ;unlike in 8051, in pic all interrupt event lead PC to this address
goto interrupt_handler

LFSR macro Address,Offset
    movlw Address
    movwf FSR
    movf Offset,W
    addwf FSR,F
    endm

;-------------------------------------------------------------------------------------------------
Start
;----------Oscillator setup
banksel OSCCON
movlw  b'01110111'
movwf  OSCCON      ; set the internal oscillator at 8 Mhz and uses internal clk
banksel PCON
bsf PCON,NOT_POR
bsf PCON,NOT_BOR

;----------Watchdog disable
;I dont think we need watch dog timer here so I am going to disable it
banksel WDTCON
movlw 0x00
movwf WDTCON

;--------------Interrupts setup
banksel INTCON
movlw b'11000000'
movwf INTCON ; global interrupts and peripheral interrupts are on
banksel PIE1 ;timer1 interrupt is on
bsf PIE1, SSPIE
bsf PIE1, TMR1IE
banksel PIR1
clrf PIR1

;---------------setting up the address of the device
banksel SSPADD
movlw slave_add
movwf SSPADD

;--------------setting up the I2C slave 7bit communication
;--------------SFRs modified: sspcon ans SSPSTAT
;---------------address is 8 bits long dont know actual address will be LA or R aligned
banksel SSPCON
movlw b'00110110'
;----------------enable clock and set sda ans scl pins as serial port pins in 7-bit slave mode
movwf SSPCON
banksel SSPSTAT
clrf SSPSTAT
;---------------------ADC setup
banksel ADCON0
movlw b'00001011' ;pin 12 is input for battery level detector and remains default input for ADC
movwf ADCON0
banksel ADCON1
movlw b'01000000' ;ADC operates at FOSC/4
movwf ADCON1
;------------------setting up the ports for input

banksel ANSEL
movlw b'11111100'
movwf ANSEL
banksel ANSELH
clrf ANSELH
bsf ANSELH,ANS11
bsf ANSELH,ANS8
bsf ANSELH,ANS9
banksel TRISC
movlw b'11001111'
movwf TRISC
banksel TRISA
movlw b'00011111'
movwf TRISA
banksel TRISB
movlw b'01110000'
movwf TRISB
banksel PORTA
clrf PORTA
banksel PORTB
clrf PORTB
banksel PORTC
clrf PORTC
banksel T1CON
movlw b'00110001' ;1:1 prescaled value timer run
movwf T1CON

banksel seconds
incf seconds
incf seconds

loop_here
nop
goto loop_here

interrupt_handler
  banksel PIR1
  btfsc PIR1, SSPIF
  goto I2C_COMM
  btfss PIR1, TMR1IF
  goto Exit
  goto timer1_ISR

I2C_COMM
  banksel INTCON
  movlw b'00000000'
  movwf INTCON
  banksel PIR1
  bcf PIR1, SSPIF

;---------------------------------------------------------------------
; The I2C code below checks for 5 states:
;---------------------------------------------------------------------
; State 1:  I2C write operation, last byte was an address byte.
; SSPSTAT bits:  S = 1, D_A = 0, R_W = 0, BF = 1
;
; State 2:  I2C write operation, last byte was a data byte.
; SSPSTAT bits:  S = 1, D_A = 1, R_W = 0, BF = 1
;
; State 3:  I2C read operation, last byte was an address byte.
; SSPSTAT bits: S = 1, D_A = 0, R_W = 1
;
; State 4:  I2C read operation, last byte was a data byte.
; SSPSTAT bits:  S = 1, D_A = 1, R_W = 1, BF = 0
;
; State 5:  Slave I2C logic reset by NACK from master.
; SSPSTAT bits: S = 1, D_A = 1, BF = 0, CKP = 1
;
; For convenience, WriteI2C and ReadI2C functions have been used.
;--------------------------------------------------------------

banksel SSPSTAT
movf SSPSTAT,W
andlw b'00101101'
banksel Temp
movwf Temp

State1
    movf Temp,w
    xorlw b'00001001'
    banksel STATUS
    btfss STATUS,Z
    goto State2       
    banksel SSPBUF
    movf SSPBUF,W
    goto Exit
  
State2
    banksel Temp
    movf Temp,w
    xorlw b'00101001'
    banksel STATUS
    btfss STATUS,Z
    goto State3
    banksel SSPBUF
    movf SSPBUF,W
    banksel on_off
    movwf on_off
    sublw sensor_off
    banksel STATUS
    btfsc STATUS,Z
    goto turnoff
    banksel on_off
    movf on_off,W
    sublw sensor_on
    banksel STATUS
    btfsc STATUS,Z
    goto turnon
    goto Exit
turnon
    banksel PORTA
    bcf PORTA,RA5
    goto Exit
    
turnoff
    banksel PORTA
    bsf PORTA,RA5
    goto Exit

State3
    banksel Temp
    movf Temp,W
    xorlw b'00001100'
    banksel STATUS
    btfss STATUS,Z
    goto State4
    
    movlw RX_BUF_LEN
    banksel ADCindex
    movwf ADCindex        ;Counter for number of ADC operations
    banksel ADCcount
    clrf ADCcount
    movlw b'00001001'
    banksel ADCON0        ;Left justified, VDD ref, AN0, ADC enable
    movwf ADCON0        ;Set the status for ADC
    nop
    nop

adc_loop
    banksel ADCON0
    bsf ADCON0, GO        ;Initiate ADC
    nop
    nop
    nop
    btfsc ADCON0, GO    ;IS ADC complete?
    goto $-1            ;If not then loop back and check again

;SAVE DATA HERE

    banksel RXBuffer
    movlw RXBuffer
    banksel FSR
    movwf FSR
    banksel ADCcount
    movf ADCcount, 0
    banksel FSR
    addwf FSR,1
    banksel ADRESH
    movf ADRESH, 0        ;Capture data
    movwf INDF

    banksel ADCcount
    incf ADCcount,F        ;Increment index
    banksel ADCON0
    movlw b'00000100'
    addwf ADCON0,1    ;Select next ADC, but keep other settings same
    banksel ADCindex
    decfsz ADCindex,F    ;Countdown the number of ADC read, loop back
    goto adc_loop
    nop
    banksel Index
    clrf Index                ; Clear the buffer index.
    LFSR RXBuffer,Index    ; Point to the buffer
    movf INDF,W            ; Get the byte from buffer.      
    goto WriteI2C
       
State4
        banksel Temp
        movf Temp,W
        xorlw b'00101100'
        banksel STATUS
        btfss STATUS,Z
        goto State5
        banksel Index
    movf Index,W
    sublw RX_BUF_LEN
    banksel STATUS
    btfsc STATUS,Z
    goto Clear_index
    goto ready
ready   
    banksel Index
    movf Index,W
    LFSR RXBuffer,Index
    movf INDF,W
    goto WriteI2C

Clear_index
    banksel Index
    clrf Index
    goto ready

        
State5
        banksel SSPCON
        movlw b'00110110'
        movwf SSPCON
        banksel SSPSTAT
        clrf SSPSTAT
        goto Exit

Exit
      banksel PIR1
        bcf PIR1,SSPIF
        banksel SSPCON
        bsf SSPCON,CKP
        goto Exit1
        
Exit1
      banksel INTCON
      movlw b'11000000'
      movwf INTCON ; global interrupts and peripheral interrupts are on
      retfie

WriteI2C
    banksel SSPSTAT
    btfsc SSPSTAT,BF        ; Is the buffer full?
    goto WriteI2C            ; Yes, keep waiting.
    banksel SSPCON            ; No, continue.

DoI2CWrite
      bcf SSPCON,WCOL        ; Clear the WCOL flag.
      banksel SSPBUF
      movwf SSPBUF            ; Write the byte in WREG
      banksel SSPCON
      btfsc SSPCON,WCOL        ; Was there a write collision?
      goto DoI2CWrite
      banksel SSPCON
      bsf SSPCON,CKP            ; Release the clock.
      banksel Index
      incf Index,F            ; Increment the buffer index.
      goto Exit
      
timer1_ISR
      banksel PIR1 ;this register contains flags including the one for timer1
      bcf PIR1,TMR1IF
      banksel seconds
      decfsz seconds
      goto Exit1
      banksel seconds
      movlw b'00000010'
      movwf seconds

banksel ADCON0
      movlw b'00101101'
      movwf ADCON0
      nop
      nop
      nop
    bsf ADCON0,GO
      nop
      nop
      nop
      btfsc ADCON0, GO    ;IS ADC complete?
      goto $-1            ;If not then loop back and check again
      banksel ADRESH
      movf ADRESH,0
      banksel battery_level
      movwf battery_level
      banksel ADRESH
      btfss ADRESH,7
      goto low_battery
    btfsc ADRESH,6
      goto high_battery
    btfss ADRESH,5
      goto low_battery
    goto high_battery

high_battery
      banksel PORTC
      bcf PORTC,RC4
      goto Exit1
low_battery
      banksel PORTC
      bsf PORTC,RC4
      goto Exit1
end