From: ian Date: Sun, 13 Feb 2005 22:18:17 +0000 (+0000) Subject: reformatting, comments, etc X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=5691e8c3ff41150d6b4f96f6d89395cd7581b46c;p=trains.git reformatting, comments, etc --- diff --git a/cebpic/i2c-test.asm b/cebpic/i2c-test.asm index b80dbca..a7c711d 100644 --- a/cebpic/i2c-test.asm +++ b/cebpic/i2c-test.asm @@ -5,43 +5,27 @@ ; pin 21 (per-pic-led, RD2/PSP2/C1IN) states: ; high H = blue (=green), low L = orange (=red), float Z = black - +;*************************************************************************** +;SETUP AND DEFINITIONS + +; CONVENTIONS: +; +; In subroutines, unless otherwise stated, W and S may have any +; value on entry and will be undefined on exit. +; +; labels ending _if_... and _endif_... are used for if ... then [... else ...] +; labels ending _loop are for loops +; labels ending _isr are at the start of interrupt service routines +; (which must end with retfie) +; other labels in lowercase are normal subroutines (ending in `return') +; labels in UPPERCASE are defined addresses (in RAM or flash) + +;--------------------------------------------------------------------------- +; boilerplate: include /usr/share/gputils/header/p18f458.inc - radix dec -; reserved for NMRA: -NMRACTRL equ 0x4 ; byte 4: state relevant to NMRA control -TRANSMITBIT equ 0x7 ; bit 7: 0/1 bit currently being transmitted -NEXTACTION equ 0x6 ; bit 6: change polarity on next interrupt y/n - -FROMSERIAL equ 0x1 ; byte 1: from-serial buffer location (in BSR5) -TOTRACK equ 0x2 ; byte 2: to-track buffer location (in BSR5) -TOTRACKBIT equ 0x3 ; byte 3: bit location of pointer within byte - -NMRA_BUFF_PAGE equ 5 - -; flash locations for PIC-dependent info: - -F_PIC_NO_U equ 20h ; flash location of PIC number -F_PIC_NO_H equ 00h -F_PIC_NO_L equ 00h - -F_I2C_CTRL_U equ 20h ; flash location of i2c control byte -F_I2C_CTRL_H equ 00h -F_I2C_CTRL_L equ 01h - -; i2c specific stuff - -I2C_BUFF_PAGE equ 4 ; put i2c relevant stuff into buffer page 4 -PIC_NO equ 00h ; pic no goes to 400h -I2C_CTRL equ 01h ; i2c ctrl bit goes to 401h -I2C_MASTER equ 0 ; bit 0 of I2C_CTRL is 1=master 0=slave - - - - ifdef SLOW_VERSION messg "hello this is the slow version" endif @@ -56,32 +40,51 @@ I2C_MASTER equ 0 ; bit 0 of I2C_CTRL is 1=master 0=slave messg "and an else" endif - org 0 - goto initialise +;--------------------------------------------------------------------------- +; ID locations layout, in flash - see README.protocol -;**************************************************************************** +F_PIC_NO equ 0x200000 +F_I2C_CTRL equ 0x200001 -; high priority interrupt +;--------------------------------------------------------------------------- +; RAM - ie, variables etc. - org 000008h - goto interrupt_high +; i2c specific stuff + udata 0x400 -; low priority interrupt +PIC_NO res 1 - org 000018h - goto interrupt_low +I2C_CTRL res 1 +I2C_CTRL_MASTER equ 0 ; bit 0 of I2C_CTRL is 1=master 0=slave ;**************************************************************************** +; VECTORS: special locations, where the PIC starts executing +; after reset and interrupts - code + org 0 + goto vector_reset -;**************************************************************************** + org 000008h + goto vector_interrupt_high + + org 000018h + goto vector_interrupt_low -macros +;**************************************************************************** +; MACROS + +;---------------------------------------- +; debugvalue(BYTE) +; writes BYTE through the serial port +; serial port hardware must be suitably initialised +; serial port transmit interrupts must be disabled +; will spin until the byte is transmitted +; Before After +; W any undefined +; S any undefined ; macro to call subroutine to transmit over serial port for debugging ; takes 8-bit value, puts in W, invokes debug_serial_transmit - ifndef SLOW_VERSION debug macro debugvalue endm @@ -94,19 +97,131 @@ debug macro debugvalue endm endif -debug_serial_transmit +;-------------------- +debugvalue_serial_transmit +; writes W through the serial port +; for use by debugvalue macro only + movwf TXREG,0 ; move contents of W (i.e. debugvalue) ; to TXREG for transmission -waitfortsr +debugvalue_waitfortsr_loop btfss TXSTA,1,0 - bra waitfortsr + bra debugvalue_waitfortsr_loop + return ;**************************************************************************** -initialise + code + +;**************************************************************************** +; PORTMANTEAU CODE +; which contains lists of checks and calls to function-specific +; routines etc. + +;---------------------------------------- +vector_reset + call serial_setup + call copy_per_pic_data + call i2c_setup + call enable_interrupts + goto main + +;---------------------------------------- +main + banksel I2C_CTRL ; ser BSR=i2c BSR (4) + btfsc I2C_CTRL,I2C_CTRL_MASTER ; check =master?, if so + goto master_main ; goto master main routine + goto slave_main ; elso goto slave main routine + +;---------------------------------------- +vector_interrupt_high + debug 'H' + goto panic + +;---------------------------------------- +vector_interrupt_low +; checks which interrupt and as soon as it finds one jumps straight +; to the relevant ISR. That routine will return with retfie and if +; there was another interrupt we will re-enter, which is OK. + + btfsc PIR1,SSPIF,0 ; check if MSSP interrupt generated, if so +; goto i2c_isr ; I2C ISR will check whether master or slave + goto panic ; nothing should generate these ATM.... + + btfsc PIR1,5,0 ; check for serial receive interrupt + goto serial_rx_isr ; receive serial + + debug 'L' ; else panic - interrupt but don't know why + goto panic + +;---------------------------------------- +enable_interrupts +; globally enable interrupts - p77 +; etc. -; serial set-up + 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) + return + +;***************************************************************************( +; FUNCTIONALITY +; these routines actually glue things together to make something that +; does something + +;---------------------------------------- +master_main +; main program for master PIC + + call led_green + +master_main_loop + goto master_main_loop + + +;---------------------------------------- +slave_main +; main program for slave PICs + + call led_red + +slave_main_loop + call wait_for_i2c_interrupt ; wait for 1st (address) byte + call wait_for_i2c_interrupt ; wait for 2nd (data) byte + btg LATD,2,0 ; toggle colour of LED + goto slave_main_loop + +;---------------------------------------- +serial_rx_isr +; what we actually do here is faff with I2C to start transmitting + 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 + +;!!!fixme - next line is wrong, surely ? + goto master_main + +;*************************************************************************** +; SERIAL PORT + +;-------------------- +serial_setup +; sets up the serial port, 9600 8N1 etc. as required by host +; interrupt is enabled for reception but not transmission ; initial config - TXSTA register p181 bcf TXSTA,6,0 ; p181, set 8-bit mode @@ -124,26 +239,29 @@ initialise bsf SPBRG,7,0 bsf SPBRG,0,0 - ; interrupt set-up for serial receive bcf IPR1,5,0 ; set to low-priority interrupt + return +;*************************************************************************** +; FLASH ID LOCATIONS -;---------------------------------------------------------------------------- - -; copy PIC-dependent info out of flash memory +;-------------------- +copy_per_pic_data +; copies PIC-dependent info out of flash memory to RAM +; see README.protocol - movlw F_PIC_NO_U ; set table pointer to point to - movwf TBLPTRU ; PIC number in flash - movlw F_PIC_NO_H + movlw (F_PIC_NO >> 16) & 0xff ; set table pointer to point to + movwf TBLPTRU ; PIC number in flash + movlw (F_PIC_NO >> 8) & 0xff movwf TBLPTRH - movlw F_PIC_NO_L + movlw F_PIC_NO movwf TBLPTRL tblrd *+ ; read then increment pointer ; (now points to i2c control byte) - movlb I2C_BUFF_PAGE ; ser BSR=i2c BSR (4) + banksel PIC_NO movf TABLAT,0,0 ; move pic number into normal memory movwf PIC_NO,1 @@ -151,20 +269,28 @@ initialise movf TABLAT,0,0 ; move i2c_ctrl byte into normal memory movwf I2C_CTRL,1 +; now have: PIC number in 400h, i2c control byte in 401h - see +; RAM variables re i2c specific stuff, above -; now have: PIC number in 400h, i2c control byte in 401h - -;---------------------------------------------------------------------------- + return -; i2c setup +;*************************************************************************** +; I2C -; NB to generate an address, take PIC_NO bits 4-0 and prepend 10 -; (i.e. all addresses are of the form 10xxxxx) +;-------------------- +i2c_setup +; sets up the I2C interface - movlb I2C_BUFF_PAGE ; ser BSR=i2c BSR (4) +; see also: +; p68 +; p314 +; p 275 ID locs -common_setup +; To generate our I2C address, we take PIC_NO bits 4-0 and prepend +; 0b10 (i.e. all addresses are of the form 0b10xxxxx) + banksel PIC_NO ; ser BSR=i2c BSR (4) +; common to master and slaves: bsf SSPSTAT,7,0 ; disable slew rate control bcf SSPSTAT,6,0 ; disable SMBus specific commands ; (whatever that means) @@ -172,16 +298,12 @@ common_setup bcf IPR1,SSPIP,0 ; make interrupt low priority +; are we master or slave ? + btfss I2C_CTRL,I2C_CTRL_MASTER,1 ; test whether PIC is master + goto i2c_setup_if_master + goto i2c_setup_if_slave -master_or_slave - - btfss I2C_CTRL,I2C_MASTER,1 ; test whether PIC is master - goto pic_master_setup ; if so, set up as master - goto pic_slave_setup ; else set up as slave - - -pic_master_setup - +i2c_setup_if_master movlw 0x08 movwf SSPCON1,0 ; set to master mode, clear top 4 bits @@ -191,172 +313,91 @@ pic_master_setup ; Fosc=20MHz, currently want clock=50kHz ; => SSPADD=99 - goto switch_i2c_on - - -pic_slave_setup + goto i2c_setup_endif_master_slave +i2c_setup_if_slave 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) + banksel PIC_NO ; 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 - +i2c_setup_endif_master_slave bsf SSPCON1,5,0 ; enable I2C mode + return -; p68 -; p314 -; p 275 ID locs - - -;---------------------------------------------------------------------------- - -; interrupt set-up - -; globally enable interrupts - p77 - 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 ; wait for 1st (address) byte - 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' - goto panic - - -;**************************************************************************** - -interrupt_low - -; check which interrupt. - 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 - - -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 - +;---------------------------------------- +i2c_isr + banksel PIC_NO ; ser BSR=i2c BSR (4) + btfsc I2C_CTRL,I2C_CTRL_MASTER ; check =master?, if so + goto i2c_master_isr ; goto master interrupt routine + goto i2c_slave_isr ; elso goto interrupt_slave -;---------------------------------------------------------------------------- -interrupt_master +;-------------------- +i2c_master_isr debug 'm' goto panic -;---------------------------------------------------------------------------- -interrupt_slave +;-------------------- +i2c_slave_isr 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 +; polls the relevant bit until the I2C interrupt flag is set, +; then returns. should not usually be used if I2C interrupts +; are enabled, clearly. + +wait_for_i2c_interrupt_loop btfss PIR1,SSPIF,0 ; check if interrupt set, if not, loop - goto wait_for_i2c_interrupt + goto wait_for_i2c_interrupt_loop + bcf PIR1,SSPIF,0 ; clear interrupt bit return +;*************************************************************************** +; PER-PIC LED -;**************************************************************************** +;---------------------------------------- led_green bcf TRISD,2,0 ; make pin RD2 an output (DS100) bsf LATD,2,0 ; set pin RD2 H (green) return +;---------------------------------------- led_black bsf TRISD,2,0 ; make pin RD2 an input (i.e. set Z, black) ; (DS100) return +;---------------------------------------- led_red bcf TRISD,2,0 ; make pin RD2 an output (DS100) bcf LATD,2,0 ; set pin RD2 L (red) return +;*************************************************************************** +; GENERALLY-USEFUL SUBROUTINES; + +;---------------------------------------- panic +; stops everything, makes LED red + debug 'x' clrf INTCON,0 ; disable all interrupts EVER debug 'y' bcf PORTC,1,0 ; switch off booster debug 'z' call led_red + panic_loop goto panic_loop