+; write a byte to pic0 via the serial port, pic0 will transmit it to
+; pic1, which will then toggle its colour (without checking the contents
+; of the byte)
; pin 21 (per-pic-led, RD2/PSP2/C1IN) states:
-; high H = green, low L = red, float Z = black
+; high H = blue (=green), low L = orange (=red), float Z = black
include /usr/share/gputils/header/p18f458.inc
+ radix dec
; reserved for NMRA:
NMRACTRL equ 0x4 ; byte 4: state relevant to NMRA control
bsf SSPSTAT,7,0 ; disable slew rate control
bcf SSPSTAT,6,0 ; disable SMBus specific commands
; (whatever that means)
-
-
+ bcf SSPCON2,7,0 ; disable general call (for now)
+ bcf IPR1,SSPIP,0 ; make interrupt low priority
master_or_slave
pic_master_setup
+ movlw 0x08
+ movwf SSPCON1,0 ; set to master mode, clear top 4 bits
+
+; set baud rate
+ movlw 100-1
+ movwf SSPADD,0 ; set baud rate; clock=Fosc/(4*(SSPADD+1))
+ ; Fosc=20MHz, currently want clock=50kHz
+ ; => SSPADD=99
+ goto switch_i2c_on
pic_slave_setup
+ movlw 0x06
+ movwf SSPCON1,0 ; set to 7bit slave mode, clear top 4 bits
+ ; (no extra start/stop interrupts)
+
+; set slave address
+ movlb I2C_BUFF_PAGE ; set BSR=i2c BSR (4)
+ movf PIC_NO,0,1 ; copy pic_no to W (000xxxxx)
+ iorlw 0x40 ; change top 3 bits t 010 (010xxxxx)
+ movwf SSPADD,0 ; move to slave address register
+ ; (bit 7=0, bits 6-0=address)
+
+ goto switch_i2c_on
+
+switch_i2c_on
+ bsf SSPCON1,5,0 ; enable I2C mode
; p68
; p314
; p 275 ID locs
-; test whether master PIC (location 20 0000h bit 0; 1 if true)
-; by doing:
-; set tblptr (tblptru/tblptrh/tblptrl)
-; tblrd *
-; result in tablat
-
-; i2c_master_setup if so, i2c_slave_setup if not
-
-
-
-
;----------------------------------------------------------------------------
bsf RCON,7,0 ; enable priority levels
bsf INTCON,7,0 ; enable high-priority interrupts
bsf INTCON,6,0 ; enable low-priority interrupts
+ bcf PIE1,3,0 ; disable master synchronous serial port
+ ; (MSSP; i.e. enable i2c) interrupts
+ ; (temporary for this simple program)
bsf PIE1,5,0 ; enable USART receive interrupt (p85)
;****************************************************************************
+;****************************************************************************
+
+main
+ movlb I2C_BUFF_PAGE ; ser BSR=i2c BSR (4)
+ btfsc I2C_CTRL,I2C_MASTER ; check =master?, if so
+ goto main_master ; goto master main routine
+ goto main_slave ; elso goto slave main routine
+
+
+;----------------------------------------------------------------------------
+
+main_master
call led_green
main_loop_led
goto main_loop_led
+;----------------------------------------------------------------------------
+
+main_slave
+
+ call led_red
+
+slave_loop
+ call wait_for_i2c_interrupt ; check buffer full? if not
+ goto slave_loop ; loop
+ call led_red ; else light LED red=received
+ call wait_for_i2c_interrupt ; wait for 2nd (data) byte
+ btg LATD,2,0 ; toggle colour of LED
+ goto slave_loop
+
+
+
;****************************************************************************
+;****************************************************************************
+
interrupt_high
debug 'H'
interrupt_low
; check which interrupt.
- debug 'L'
+ btfsc PIR1,SSPIF,0 ; check if MSSP interrupt generated, if so
+; goto interrupt_ms ; check whether master or slave
+ goto panic ; nothing should generate these ATM....
+ btfsc PIR1,5,0 ; check whether serial receive interrupt bit set
+ ; if so
+ goto serial_receive ; receive serial
+ debug 'L' ; else panic
goto panic
-; serial only?
-;****************************************************************************
+interrupt_ms
+ movlb I2C_BUFF_PAGE ; ser BSR=i2c BSR (4)
+ btfsc I2C_CTRL,I2C_MASTER ; check =master?, if so
+ goto interrupt_master ; goto master interrupt routine
+ goto interrupt_slave ; elso goto interrupt_slave
-serial_receive
- debug 'S'
+
+;----------------------------------------------------------------------------
+interrupt_master
+ debug 'm'
goto panic
-; serial byte to say pic #, LED flash pattern, look pattern up in table?
-; (to test use of flash memory and lookup therein)
-; think about serial msg format (in general and (simpler) for here)
+;----------------------------------------------------------------------------
+interrupt_slave
+ debug 's'
+ goto panic
;****************************************************************************
+serial_receive
+ bsf SSPCON2,SEN,0 ; i2c START
+ call wait_for_i2c_interrupt
+ movlw 0x41 ; transmit address 0100 0001
+ call wait_for_i2c_interrupt
+ btfss SSPCON2,ACKSTAT,0 ; check for ack from slave (=0), if no
+ goto panic ; then panic, else
+ movff RCREG,SSPBUF ; copy byte from serial to i2c buffer
+ call wait_for_i2c_interrupt
+ btfss SSPCON2,ACKSTAT,0 ; check for ack from slave (=0), if no
+ goto panic ; then panic, else
+ bsf SSPCON2,PEN,0 ; i2c STOP
+ call wait_for_i2c_interrupt
+ goto main_master
+
+
+wait_for_i2c_interrupt
+ btfss PIR1,SSPIF,0 ; check if interrupt set, if not, loop
+ goto wait_for_i2c_interrupt
+ bcf PIR1,SSPIF,0 ; clear interrupt bit
+ return
+
+;****************************************************************************
led_green
bcf TRISD,2,0 ; make pin RD2 an output (DS100)
bsf LATD,2,0 ; set pin RD2 H (green)