;;; I2C test ; ; Modified by Terry Sturtevant ; May 29, 2007 ; ;i2c_bitbash.asm ; added bit-bashing code for i2c ; ; Timing accomplished using interrupts and Timer 0 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; assembler directives ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LIST P=PIC18F452, F=INHX32, C=160, N=0, ST=OFF, MM=OFF, X=ON #include P18F452.inc CONFIG OSC=HS ;select HS oscillator CONFIG PWRT=ON, BOR=ON, BORV=42 CONFIG WDT=OFF, LVP=OFF ;disable watchdog timer ; and low voltage power ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cblock 0x000 ;??? _100us_count _1ms_count _10ms_count _100ms_count _1s_count _btest1:8 _btest1_head ;next avialable position (for write) _btest1_tail ;next to display (for read) endc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; equates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _TEST1 equ 0x01 _TEST2 equ 0x0B _TEN equ d'10' _BITS_IN_BYTE equ d'8' _BOTTOM_NIBBLE equ 0x0F _TOP_NIBBLE equ 0xF0 _ASCII_DIGIT_OFFSET equ 0x30 _HEX_DIGIT_OFFSET equ 0x37 _CARRY_BIT equ 0 ;in STATUS register ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;timer 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;delay_count equ ? ;for 10ms count delay_count equ ? ;for 1ms count ;delay_count equ ? ;for 0.1ms count _TICK_FLAG equ 0 _1MS_FLAG equ 1 _10MS_FLAG equ 2 _100MS_FLAG equ 3 _1S_FLAG equ 4 _I2C_TIMEOUT_FLAG equ 5 ;to allow getting out if acknowledge missing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;LEDs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _LEFT_LED equ ? _CENTRE_LED equ ? _RIGHT_LED equ ? _ALIVE_LED equ ? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _SCL equ ? _SDA equ ? _I2C_100KHZ equ ? _I2C_SLOW equ ? ;_I2C_SLOW equ d'128' _I2C_BB_DELAY equ d'20' ;delay in clock cycles ;15 is not enough, hangs after ;a few seconds ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;HM6352 i2c equates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;device addresses _HMC6352_WRITE equ 0x42 _HMC6352_READ equ 0x43 ;commands _HMC6352_CMD_WRITE_EEPROM equ 0x77 _HMC6352_CMD_READ_EEPROM equ 0x72 _HMC6352_CMD_WRITE_RAM equ 0x47 _HMC6352_CMD_READ_RAM equ 0x67 _HMC6352_CMD_READ_HEADING equ 0x41 ;internal eeprom addresses _HMC6352_SLAVE_ADDRESS equ 0x00 _HMC6352_OP_SW_VERSION equ 0x07 _HMC6352_OP_MODE_BYTE equ 0x08 ;internal RAM addresses _HMC6352_OP_MODE_CONTROL equ 0x74 _HMC6352_OUTPUT_MODE_CONTROL equ 0x4E ;default is HEADING ;output modes _HMC6352_OUTPUT_HEADING equ 0x00 ;only one likely to be used _HMC6352_OUTPUT_RAW_X equ 0x01 _HMC6352_OUTPUT_RAW_Y equ 0x02 _HMC6352_OUTPUT_X equ 0x03 _HMC6352_OUTPUT_Y equ 0x04 ;mode control _HMC6352_RATE_1HZ equ 0x00 ;only one to be used _HMC6352_RATE_5HZ equ 0x20 _HMC6352_RATE_10HZ equ 0x40 _HMC6352_RATE_20HZ equ 0x60 _HMC6352_MODE_STANDBY equ 0x00 ;only one to be used _HMC6352_MODE_QUERY equ 0x01 _HMC6352_MODE_CONTINUOS equ 0x02 _HMC6352_PERIODIC_SR equ 0x10 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;LCD ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; port E bits _LCD_RS equ ? _LCD_ENABLE equ ? ;commands _LCD_CLEAR equ ? _LCD_RETURN_HOME equ ? _LCD_ENTRY_MODE_MASK equ ? _LCD_DISPLAY_CONTROL_MASK equ ? _LCD_SHIFT_MASK equ ? _LCD_ADDRESS_MASK equ ? ;;; ;_LCD entry options _LCD_ENTRY_INCREMENT equ ? _LCD_ENTRY_DECREMENT equ ? _LCD_ENTRY_SHIFT equ ? _LCD_ENTRY_DONT_SHIFT equ ? ;LCD display options _LCD_DISPLAY_ON equ ? _LCD_DISPLAY_OFF equ ? _LCD_DISPLAY_CURSOR_ON equ ? _LCD_DISPLAY_CURSOR_OFF equ ? _LCD_DISPLAY_CURSOR_BLINK equ ? _LCD_DISPLAY_CURSOR_DONT_BLINK equ ? ;LCD shift options _LCD_SHIFT_MASK equ ? _LCD_SHIFT_SHIFT_DISPLAY equ ? _LCD_SHIFT_MOVE_CURSOR equ ? _LCD_SHIFT_RIGHT equ ? _LCD_SHIFT_LEFT equ ? ;LCD address options _LCD_LINE1_BEGIN equ ? _LCD_LINE2_BEGIN equ ? _LCD_CLEAR_DELAY equ ? ;longest delay in ms ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; macro definitions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; movlf - command to move a literal value into a file register movlf macro imm,dest movlw imm movwf dest endm ;;LCD macros LCD_assert_command macro bcf PORTE,_LCD_RS endm LCD_assert_data macro ;??? endm LCD_enable macro ;??? endm LCD_not_enable macro ;??? endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;LCD_write2buffer ;char starts in WREG ; ; _LCD_upper:8 ;reserve 8 bytes for upper line ; _LCD_lower:8 ;reserve 8 bytes for lower line ; _LCD_upper_head ;next avialable position (for write) ; _LCD_lower_head ;next avialable position (for write) ; _LCD_upper_tail ;next to display (for read) ; _LCD_lower_head ;next to display (for read) ; _LCD_wbuf_tmp ;temp ; _LCD_rbuf_tmp ;temp ;loc indicates beginning address of buffer ;ptr is variable with position in buffer LCD_write2buffer macro loc,ptr ;??? endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;LCD_readbuffer ; ; _LCD_upper:8 ;reserve 8 bytes for upper line ; _LCD_lower:8 ;reserve 8 bytes for lower line ; _LCD_upper_head ;next avialable position (for write) ; _LCD_lower_head ;next avialable position (for write) ; _LCD_upper_tail ;next to display (for read) ; _LCD_lower_head ;next to display (for read) ;loc indicates beginning address of buffer ;ptr is variable with position in buffer LCD_readbuffer macro loc,ptr ;??? endm LCD_write_upper macro ;??? endm LCD_write_lower macro ;??? endm LCD_read_upper macro ;??? endm LCD_read_lower macro ;??? endm LCD_clear_upper macro ;??? endm LCD_write_command macro ;??? endm LCD_read_command macro ;??? endm ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;_LCD_BUFFER_LIMIT equ d'24' ;time to roll over ;_LCD_PENDING equ 5 ;to indicate buffer not empty ;_LCD_buffer:24 ;reserve 24 bytes for buffer ;_LCD_buffer_head ;next avialable position (for write) ;_LCD_buffer_tail ;next avialable position (for read) ;loc indicates beginning address of buffer ;ptr is variable with position in buffer ;returns carry set if buffer overflowed write_buffer macro LOC,ptr,LIMIT ;??? endm read_buffer macro LOC,ptr,LIMIT ;??? endm LCD_write_buffer macro ;??? endm LCD_read_buffer macro ;??? endm LCD_clear_buffer macro ;??? endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C bit-bashing macros ;changed to be like open-drain ; assume pull-ups on SCL, SDA, so leave the PORTC bits low, and just ; change TRISC bits to make high or input ;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_bb_sda_out macro bcf TRISC,_SDA endm i2c_bb_sda_in macro bsf TRISC,_SDA endm i2c_bb_sda_hi macro bsf TRISC,_SDA endm i2c_bb_sda_lo macro bcf TRISC,_SDA endm i2c_bb_scl_hi macro bsf TRISC,_SCL endm i2c_bb_scl_lo macro bcf TRISC,_SCL endm ;delays for _I2C_BB_DELAY instruction cycles ; i2c_bb_sdelay macro movlw _I2C_BB_DELAY decfsz WREG bra $-2 endm ;uses bit in carry i2c_1bit_out macro bnc $+6 ;set bit if high i2c_bb_sda_hi bra $+4 i2c_bb_sda_lo ;otherwise clear i2c_bb_sdelay i2c_bb_scl_hi i2c_bb_sdelay i2c_bb_scl_lo i2c_bb_sdelay endm ;returns bit in carry i2c_1bit_in macro i2c_bb_sdelay i2c_bb_scl_hi i2c_bb_sdelay btfss PORTC,_SDA bra $+6 bsf STATUS,_CARRY_BIT ;set bit if high bra $+4 bcf STATUS,_CARRY_BIT ;otherwise clear nop i2c_bb_sdelay i2c_bb_scl_lo i2c_bb_sdelay endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;HMC6352 macros ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;result returned in _I2C_tmpRH ;_I2C_tmpH arg ;_I2C_tmpL data ;HM6352_read_arg_data HM6352_read_version macro movlf _HMC6352_CMD_READ_EEPROM,_I2C_tmpH movlf _HMC6352_OP_SW_VERSION,_I2C_tmpL rcall HM6352_read_arg_data endm ;result returned in _I2C_tmpRH HM6352_read_OP_mode macro movlf _HMC6352_CMD_READ_RAM,_I2C_tmpH movlf _HMC6352_OP_MODE_CONTROL,_I2C_tmpL rcall HM6352_read_arg_data endm ;result returned in _I2C_tmpRH HM6352_read_OUTPUT_mode macro movlf _HMC6352_CMD_READ_RAM,_I2C_tmpH movlf _HMC6352_OUTPUT_MODE_CONTROL,_I2C_tmpL rcall HM6352_read_arg_data endm ;initiates reading but doesn't get result HM6352_read_heading_Query macro movlf _HMC6352_CMD_READ_HEADING,_I2C_tmpH rcall HM6352_write_arg endm ;initiates reading but doesn't get result HM6352_read_heading_Standby macro movlf _HMC6352_CMD_READ_HEADING,_I2C_tmpH rcall HM6352_write_arg endm ;result returned in _I2C_tmpRH, _I2C_tmpRL HM6352_get_heading_SQ macro rcall HM6352_read_data_data endm ;result returned in _I2C_tmpRH, _I2C_tmpRL HM6352_read_heading_Cont macro rcall HM6352_read_data_data endm ;takes immediate value for operational mode HM6352_write_OP_mode macro dat movlf _HMC6352_CMD_WRITE_RAM,_I2C_tmp movlf _HMC6352_OP_MODE_CONTROL,_I2C_tmpH movlf dat,_I2C_tmpL rcall HM6352_write_arg_data_data endm ;takes immediate value for output mode HM6352_write_OUTPUT_mode macro dat movlf _HMC6352_CMD_WRITE_RAM,_I2C_tmp movlf _HMC6352_OUTPUT_MODE_CONTROL,_I2C_tmpH movlf dat,_I2C_tmpL rcall HM6352_write_arg_data_data endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;misc macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Before reading rtc, _TICK_FLAG should be cleared. ;After reading, check it. ;If flag is set (meaning it has updated), reread. tick_copy macro tickl, tickm, tickh bcf _timer_flags,_TICK_FLAG ;in case we're interrupted movff _tick_countL,tickl movff _tick_countM,tickm movff _tick_countH,tickh btfsc _timer_flags,_TICK_FLAG bra $-10 endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; word add ; asumes both operands are low bytes of word ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wadd macro src,dest ;??? endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; word subtract (dest-src)->dest ; asumes both operands are low bytes of word ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wsub macro src,dest ;??? endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; word compare src<=dest? ; asumes both operands are low bytes of word ;returns carry set if src<=dest ;uses _wtmp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wle macro src,dest ;??? endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; vectors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0x0000 ;reset vector goto start ;beginning of program org 0x0008 ;high priority interrupt vector goto high_isr ; org 0x0018 ;low priority interrupt vector goto low_isr ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;************************************************************************ ;;; outer blocks ;;; initialization ;;; main ;;; high_isr ;;; low_isr ;;;;;;;;;;************************************************************************ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; initialization ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start rcall Init_ADC rcall Init_LED rcall Init_T0 rcall Init_T1 bsf RCON,IPEN ;set up interrupts bcf PIR1,CCP1IF ;clear flag since we're using it ;??? bsf INTCON,GIEL ;allow low priority ints now bsf INTCON,GIEH rcall Init_LCD ;timer0 and interrupts must be initialized first rcall Init_I2C_bb rcall Init_debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; main (infinite loop) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; main_l main_1ms btfss _timer_flags,_1MS_FLAG ;test if it's time to do 1ms events bra main_10ms ;check next interval ;do 1ms tasks here ;??? bra main_l ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; high priority interrupt routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; high_isr ;??? hisr_done retfie FAST ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; low priority interrupt routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; low_isr ;??? retfie ; _BSRcopyl ;;;;;;;;;;************************************************************************ ;;; preipheral initialization routines ;;; Timers ;;; I/O ;;;;;;;;;;************************************************************************ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;initialize Timer0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init_T0 ;initialize Timer0 ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;initialize Timer1 ;Timer1 and Timer3 can be used for capture/compare ;CCP pins are ; CCP1 RC2 ; CCP2 RC1 (Go figure!) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init_T1 ;initialize Timer1 for compare ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;initialize LCD ; ; PORTE,0 ;RS ; PORTE,1 ;E ; ; PORTD,4 ;DB4 ; PORTD,5 ;DB5 ; PORTD,6 ;DB6 ; PORTD,7 ;DB7 ; ;uses timer0 delays, so must be after Timer0 is initialized and interrupts are enabled ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init_LCD ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;initialize LED ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init_LED ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;initialize ADC ;must be done before PORTA will work ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init_ADC ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;initialize I2C ;NOT WORKING YET ;Master mode ; RC3 SCL ; RC4 SDA ;Peatman p. 246 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init_I2C movf TRISC ;get register ;set I2C bits as input bsf WREG,_SCL bsf WREG,_SDA movwf TRISC movlf _I2C_SLOW,SSPADD ;try to slow down movlf ? ,SSPSTAT ;turn off slew rate control (std. speed) ; bsf SSPCON1, SSPEN ;(Huang) movlf ? ,SSPCON1 ;(PEATMAN) ; |||||||- ; ||||||-- ; |||||--- ; ||||---- ; |||----- ; ||------ ; |------- ; ------- return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;initialize I2C using bit-bashing ;Master mode ; RC3 SCL ; RC4 SDA ;assume pull-ups as per I2C definition ;leave SDA, SCL LO, toggle TRISC to allow pull-ups to make HI ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init_I2C_bb ;set idle state, i.e. leave to pull-ups movf TRISC bsf WREG,_SCL bsf WREG,_SDA movwf TRISC ;set up like open drain i.e. always low - pull-ups will make high when ; TRISC changes pins to input movf PORTC bcf WREG,_SCL bcf WREG,_SDA movwf PORTC return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;initialize HM6352 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init_HM6352 HM6352_write_OP_mode _HMC6352_MODE_STANDBY movlf d'5',_time_ms ;delay rcall delayms ; HM6352_write_OP_mode _HMC6352_RATE_10HZ+ _HMC6352_MODE_QUERY HM6352_write_OUTPUT_mode _HMC6352_OUTPUT_HEADING movlf d'5',_time_ms ;delay rcall delayms HM6352_write_OP_mode _HMC6352_RATE_10HZ+ _HMC6352_MODE_CONTINUOS+ _HMC6352_PERIODIC_SR return ;;;;;;;;;;************************************************************************ ;;; preipheral handler routines ;;; Timers ;;; I/O ;;;;;;;;;;************************************************************************ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; interrupt based timer using Timer0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; timer0_isr ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C assert start ; non-bit-bashing******************* ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_start movlf b'00111000',SSPCON1 ;(PEATMAN) not idle, ans clears error bits bsf ?,SEN i2c_lp1 btfsc ?,SEN ; wait until complete bra i2c_lp1 return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C assert stop ; non-bit-bashing******************* ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_stop bsf SSPCON2,PEN i2c_lp2 btfsc ?,PEN ; wait until complete bra i2c_lp2 return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C assert restart ; non-bit-bashing******************* ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_restart bsf SSPCON2, ? i2c_lp3 btfsc ?,? ; wait until complete bra i2c_lp3 return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C write value in WREG ; non-bit-bashing******************* ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_write ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C enable receive (value returned in WREG) ; non-bit-bashing******************* ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_read ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C acknowledge receive ; non-bit-bashing******************* ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_ack_receive ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C negative acknowledge ; non-bit-bashing******************* ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_nack_receive ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C check transmit acknowledge ; non-bit-bashing******************* ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_trans_check_ack ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C routines ; bit-bashing+++++++++++++++++++++++ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C assert start ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_start_bb i2c_bb_sda_hi i2c_bb_scl_hi i2c_bb_sdelay i2c_bb_sda_lo i2c_bb_sdelay i2c_bb_scl_lo i2c_bb_sdelay return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C assert stop ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_stop_bb i2c_bb_sda_lo i2c_bb_scl_lo i2c_bb_sdelay i2c_bb_scl_hi i2c_bb_sdelay i2c_bb_sda_hi i2c_bb_sdelay i2c_bb_sda_in i2c_bb_sdelay return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C assert restart ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_restart_bb rcall i2c_stop_bb rcall i2c_start_bb return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C acknowledge receive ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_ack_receive_bb bcf STATUS,_CARRY_BIT ;set low nop i2c_1bit_out i2c_bb_sda_in i2c_bb_sdelay return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C negative acknowledge ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_nack_receive_bb bsf STATUS,_CARRY_BIT ;set high i2c_1bit_out i2c_bb_sda_in i2c_bb_sdelay return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C check transmit acknowledge ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;_I2C_TIMEOUT_FLAG ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_trans_check_ack_bb i2c_bb_sda_in i2c_1bit_in bsf _timer_flags,_I2C_TIMEOUT_FLAG ;right now nothing clears this i2ctc_bb btfsc STATUS,_CARRY_BIT ;set high bra i2ctc_bb1 bra i2ctc_bb2 i2ctc_bb1 btfsc _timer_flags,_I2C_TIMEOUT_FLAG ;clear if timeout happened bra i2ctc_bb i2ctc_bb2 i2c_bb_sdelay return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C write value in WREG ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_write_bb movwf _I2C_tmp_bb2 movlf _BITS_IN_BYTE, _I2C_tmp_bb1 i2cwbb1 movf _I2C_tmp_bb2,W rlcf WREG movwf _I2C_tmp_bb2 i2c_1bit_out decfsz _I2C_tmp_bb1,F bra i2cwbb1 i2c_bb_sdelay return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C enable receive (value returned in WREG) ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; i2c_read_bb i2c_bb_sda_in movlf _BITS_IN_BYTE, _I2C_tmp_bb1 i2crbb1 i2c_1bit_in rlcf _I2C_tmp_bb2,W movwf _I2C_tmp_bb2 decfsz _I2C_tmp_bb1,F bra i2crbb1 i2c_bb_sdelay movf _I2C_tmp_bb2,W nop return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;HMC6352 routines ; bit-bashing+++++++++++++++++++++++ ; RC4 SDA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;_I2C_tmpH command ; bit-bashing+++++++++++++++++++++++ HM6352_write_arg rcall i2c_start_bb movlw _HMC6352_WRITE rcall i2c_write_bb rcall i2c_trans_check_ack_bb ;check for ACK from slave movf _I2C_tmpH,W ;command to issue rcall i2c_write_bb rcall i2c_trans_check_ack_bb ;check for ACK from slave rcall i2c_stop_bb return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C write register, data ; bit-bashing+++++++++++++++++++++++ ;_I2C_tmpH arg (command) ;_I2C_tmpL dat ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HM6352_write_arg_data ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C write register, data,data ;_I2C_tmp arg ;_I2C_tmpH dat1 ;_I2C_tmpL dat2 ; bit-bashing+++++++++++++++++++++++ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HM6352_write_arg_data_data ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C read ; bit-bashing+++++++++++++++++++++++ ; result returned in _I2C_tmpRH ;not actually called, therefore not tested ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HM6352_read rcall i2c_start_bb movlw _HMC6352_READ rcall i2c_write_bb ;send slave rcall i2c_trans_check_ack_bb ;check for ACK from slave rcall i2c_read_bb movwf _I2C_tmpRH ;save result ; rcall i2c_ack_receive_bb ;acknowledge receipt of data rcall i2c_nack_receive_bb ;acknowledge receipt of data rcall i2c_stop_bb return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C read command, data ;_I2C_tmpH arg ;_I2C_tmpL data ; bit-bashing+++++++++++++++++++++++ ; result returned in _I2C_tmpRH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HM6352_read_arg_data ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;I2C read data, data eg. heading ; bit-bashing+++++++++++++++++++++++ ; result returned in _I2C_tmpRH, _I2C_tmpLH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HM6352_read_data_data ;??? return ;;;;;;;;;;************************************************************************ ;;; other routines ;;; math ;;; data manipulation ;;;;;;;;;;************************************************************************ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;hex_2_dec ;single byte binary (0-FF) to 3 digit (0-255) ;single byte starts in WREG ; from Mazidi et. al ;uses variables _numerator, _quotient, ;results returned in _decL, _decM, _decH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hex_2_dec ;??? return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; converts 16 bit binary value to BCD ;need to convert bytes to decimal to display ;uses ; _binH ; _binL ;contents are destroyed ; _bcdH ; _bcdM ; _bcdL ;results ; _bcd_temp ;temporary variable ;working ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; bin2bcd ;??? b2bdone return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; converts bottom nibble of WREG to ASCII ; returns in WREG ;seems to work May 28, 2007 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hex2ASCII ;??? return end