From: ceb Date: Mon, 3 Jan 2005 19:17:44 +0000 (+0000) Subject: minor changes X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=ac1661385e5e180ace70b9c5d022fe67f178163c;p=trains.git minor changes Use bit7 for 'last packet' indicator in NMRA packets, not bit0; changed in README.protocol and nmra-stream.asm --- diff --git a/cebpic/README.protocol b/cebpic/README.protocol index 928fd41..cbe2672 100644 --- a/cebpic/README.protocol +++ b/cebpic/README.protocol @@ -1,10 +1,10 @@ NMRA packets from the computer to the PIC should consist of 8-bit bytes. -bits 7-1 contain the data to be sent to the track -bit 0 is 1 if the byte is the last in the packet and 0 otherwise +bits 6-0 contain the data to be sent to the track +bit 7 is 1 if the byte is the last in the packet and 0 otherwise The first 14 data bits in the NMRA packet should be 1s. -(i.e. the first two complete bytes should be 11111110 11111110) +(i.e. the first two complete bytes should be 01111111 01111111) (packets beginning with some other sequence are reserved for non-NMRA messages) Maximum NMRA message length = 16 bytes (i.e. 112 bits). diff --git a/cebpic/nmra-stream.asm b/cebpic/nmra-stream.asm index 51a1b95..6d1592c 100644 --- a/cebpic/nmra-stream.asm +++ b/cebpic/nmra-stream.asm @@ -1,19 +1,7 @@ -;ERRORS: - -; 1red = high interrupt bit set -; 2red = low interrupt bit set by something which isn't timer0 or the USART - - ; pin 21 (per-pic-led, RD2/PSP2/C1IN) states: high H = green, low L = red, float Z = black -; *******will need to deal with initial short circuit first - - - - - include /usr/share/gputils/header/p18f458.inc @@ -50,24 +38,6 @@ TOTRACKBIT equ 0x3 ; byte 3: bit location of pointer within byte initialise -; 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 - -; interrupt set-up for serial receive - bsf PIE1,5,0 ; enable USART receive interrupt (p85) - bsf IPR1,5,0 ; set to low-priority interrupt - -; interrupt set-up for timer0 interrupt p79/80 - bsf INTCON,5,0 ; enable timer0 interrupts - bcf INTCON2,2,0 ; timer0 overflow low priority - - -;----------------------------------------------------------------------------------------- - - ; serial set-up ; initial config - TXSTA register p181 @@ -89,7 +59,7 @@ initialise ;----------------------------------------------------------------------------------------- -; timer set-up +; timer 0 set-up ; LED pin (21) initialisation bcf TRISE,4,0 ; turn off PSPMODE (Data Sheet p100/101) @@ -108,45 +78,63 @@ initialise ; initialise buffers (for BSR5, for nmra from-serial/to-track buffers) movlw 5 - movwf BSR,0 ; set BRS to 5 + movwf BSR,0 ; set BSR to 5 clrf NMRACTRL,0 ; for bits relevant to control of nmra stream clrf FROMSERIAL,0 ; for location of write-from-usart pointer within BSR5 clrf TOTRACK,0 ; for location of send-to-track pointer within BSR5 ; all in access bank + ;----------------------------------------------------------------------------------------- + +; initialise next action/transmit bit + bsf NMRACTRL,NEXTACTION,0 + bsf NMRACTRL,TRANSMITBIT,0 + +; initialise TOTRACKBIT bitmask + movlw 0x80 + movwf TOTRACKBIT,0 ; make bit mask be 1000 0000 + +; initialise booster direction + bsf TRISC,0,0 ; make pin 0 (booster direction) output + bcf PORTC,0,0 ; set low initially + ; set booster pwm high bsf TRISC,1,0 ; make pin 1 (booster pwm) output bsf PORTC,1,0 ; booster pwm high -; *** also need to deal with initial short circuit state *** -; initialise booster direction - bsf TRISC,0,0 ; make pin 0 (booster direction) output +;----------------------------------------------------------------------------------------- -; initialise next action/transmit bit - bsf NMRACTRL,NEXTACTION,0 - bsf NMRACTRL,TRANSMITBIT,0 +; 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 + +; interrupt set-up for serial receive + bsf PIE1,5,0 ; enable USART receive interrupt (p85) + bsf IPR1,5,0 ; set to low-priority interrupt + +; interrupt set-up for timer0 interrupt p79/80 + bsf INTCON,5,0 ; enable timer0 interrupts + bcf INTCON2,2,0 ; timer0 overflow low priority ;***************************************************************************************** main_loop_led call led_green - call waiting - call led_black - call waiting - goto main_loop_led + goto main_loop_led ;***************************************************************************************** interrupt_high - call led_red - call waiting - retfie 1 + goto panic ;***************************************************************************************** @@ -158,10 +146,11 @@ interrupt_low goto serial_receive btfss INTCON,2,0 ; check whether timer0 interrupt set goto timer0_interrupt - call led_red - call waiting - call led_red - retfie 1 ; return from interrupt to main if spurious interrupt + goto panic + +; if 2 interrupts are set at once the 2nd will generate a new interrupt on leaving +; the interrupt routine + ;***************************************************************************************** @@ -171,18 +160,18 @@ serial_receive movwf FSR0H,0 ; set high byte of IND0 pointer movff RCREG,IND0 ; copy to received register incf FROMSERIAL,1,0 ; advance FROMSERIAL pointer by 1 byte - btfss RCREG,0,0 ; check if bit 0 is set + btfss RCREG,7,0 ; check if bit 7 is set call advance_write_buffer ; if so, move to next buffer - call led_red - call waiting - return + retfie 1 +; *** I *think* the interrupt bit is cleared by reading out of RCREG +; but this may be something to try in debugging if stuff doesn't work advance_write_buffer ; check if on 1st byte of new buffer anyway (i.e. last 4 bits = 0) - movff FROMSERIAL,W ; copy FROMSERIAL pointer location to W + movf FROMSERIAL,0,0 ; copy FROMSERIAL pointer location to W andlw 0xF ; investigate last 4 bits ; if zero (i.e. overflowed to next buffer), branch to overflow check @@ -195,7 +184,7 @@ advance_write_buffer movlw 0xF andwf FROMSERIAL,1,0 swapf FROMSERIAL,1,0 - + fromserial_overflow ; clear bit 6 (will set back to buffer 0 if has overflowed to 4) bcf FROMSERIAL,6,0 @@ -215,7 +204,7 @@ timer0_interrupt ; check next action - if 0, change to 1 and return btfsc NMRACTRL,NEXTACTION,0 goto toggle_output - bsf + bsf NMRACTRL,NEXTACTION,0 retfie 1 @@ -255,19 +244,14 @@ decide_next_bit read_from_buffer -; if no, find current to-track byte and bit -; (and TRANSMITBIT with 0x1) - - movff TOTRACKBIT,W,0 - andlw 0x1 +; if currently on bit 7, want to skip to bit 6 -; checking whether TRANSMITBIT (bit mask) is at bit 0 -; (i.e. whether andlw 0x1 is 1 (on bit 0) or 0 (not on bit 0) + btfss TOTRACKBIT,7,0 + rrncf TOTRACKBIT,1,0 ; rotate mask right - bnz advance_pointer - -; if not on bit 0 (i.e. if the and above results in 0), -; set na=cb=bit value, advance bit (i.e. rotate TRANSMITBIT left), return +; if not on bit 7 , +; set na=cb=bit value, advance bit (i.e. rotate TRANSMITBIT right), +; check if bit7, if so, advance byte, return movff TOTRACK,FSR1L ; set low byte of IND1 pointer movlw 5 @@ -281,35 +265,45 @@ read_from_buffer zero_bit_to_track bcf NMRACTRL,TRANSMITBIT,0 bcf NMRACTRL,NEXTACTION,0 - call advance_bit - retfie 1 + goto advance_bit one_bit_to_track bsf NMRACTRL,TRANSMITBIT,0 bsf NMRACTRL,NEXTACTION,0 - call advance_bit + goto advance_bit + + + +advance_bit +; rotate tranmitbit to next position + + rrncf TOTRACKBIT,1,0 ; rotate mask right + + btfss TOTRACKBIT,7,0 + call advance_pointer + retfie 1 advance_pointer -; if currently on the last bit of the byte (bit 0), then check whether it is 1 or 0 +; currently on bit 7 of the byte, after having read rest of byte to track; check whether it is 1 or 0 movff TOTRACK,FSR1L movlw 5 movwf FSR1H,0 movff INDF1,W,0 - andlw 0x1 + andlw 0x80 - bnz advance_write_buffer - bra advance_write_byte + bnz advance_read_buffer + bra advance_read_byte -advance_write_buffer +advance_read_buffer -; move pointer to next buffer byte 0 +; move pointer to next buffer ; check if on 1st byte of new buffer anyway (i.e. last 4 bits = 0) movff TOTRACK,W ; copy TOTRACK pointer location to W @@ -329,11 +323,6 @@ advance_write_buffer totrack_overflow ; clear bit 6 (will set back to buffer 0 if has overflowed to 4) bcf TOTRACK,6,0 - -; advance to bit7 - - movlw 0x1 - movwf TOTRACKBIT,0 ; write na=cb=1 and return @@ -341,15 +330,12 @@ totrack_overflow -advance_write_byte +advance_read_byte ; advance to next byte of buffer (increment TOTRACK) +; (will be on bit 7 at this point anyway so no need to change TOTRACKBIT) incf TOTRACK,1,0 -; advance to bit7 - - movlw 0x1 - movwf TOTRACKBIT,0 ; set na=cb=new bit value @@ -364,35 +350,9 @@ advance_write_byte -advance_bit -; rotate tranmitbit to next position - - rlncf TOTRACKBIT,1,0 ; rotate mask left - - - -; use rotate through carry? -; rotate mask register for anding? would also provide easy check for which bit I'm on -; use top bit for last byte? signed integer arithmetic possible (branch if -ve etc.) - - ;***************************************************************************************** -waiting -; change - timer0 now for NMRA timer; run this off timer0+counter - - bcf INTCON,2,0 ; clear timer0 interrupt bit (p109) - clrf TMR0H,0 ; p107 set high bit of timer0 to 0 (buffered, - ; so only actually set when write to tmr0l occurs) - clrf TMR0L,0 ; set low bit o timer0 - timer now set to 0000h -loop - btfss INTCON,2,0 ; check whethr tiomer0 interrupt has been set - - ; skip next instruction if so - bra loop - return - - led_green bcf TRISD,2,0 ; make pin RD2 an output (DS100) @@ -409,6 +369,14 @@ led_red return +panic + bcf INTCON,7,0 ; disable high-priority interrupts + bcf INTCON,6,0 ; disable low-priority interrupts + bcf PORTC,1,0 ; switch off booster +panic_loop + call led_red + goto panic_loop + ;***************************************************************************************** end diff --git a/detpic/nmra-stream.asm b/detpic/nmra-stream.asm index 51a1b95..6d1592c 100644 --- a/detpic/nmra-stream.asm +++ b/detpic/nmra-stream.asm @@ -1,19 +1,7 @@ -;ERRORS: - -; 1red = high interrupt bit set -; 2red = low interrupt bit set by something which isn't timer0 or the USART - - ; pin 21 (per-pic-led, RD2/PSP2/C1IN) states: high H = green, low L = red, float Z = black -; *******will need to deal with initial short circuit first - - - - - include /usr/share/gputils/header/p18f458.inc @@ -50,24 +38,6 @@ TOTRACKBIT equ 0x3 ; byte 3: bit location of pointer within byte initialise -; 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 - -; interrupt set-up for serial receive - bsf PIE1,5,0 ; enable USART receive interrupt (p85) - bsf IPR1,5,0 ; set to low-priority interrupt - -; interrupt set-up for timer0 interrupt p79/80 - bsf INTCON,5,0 ; enable timer0 interrupts - bcf INTCON2,2,0 ; timer0 overflow low priority - - -;----------------------------------------------------------------------------------------- - - ; serial set-up ; initial config - TXSTA register p181 @@ -89,7 +59,7 @@ initialise ;----------------------------------------------------------------------------------------- -; timer set-up +; timer 0 set-up ; LED pin (21) initialisation bcf TRISE,4,0 ; turn off PSPMODE (Data Sheet p100/101) @@ -108,45 +78,63 @@ initialise ; initialise buffers (for BSR5, for nmra from-serial/to-track buffers) movlw 5 - movwf BSR,0 ; set BRS to 5 + movwf BSR,0 ; set BSR to 5 clrf NMRACTRL,0 ; for bits relevant to control of nmra stream clrf FROMSERIAL,0 ; for location of write-from-usart pointer within BSR5 clrf TOTRACK,0 ; for location of send-to-track pointer within BSR5 ; all in access bank + ;----------------------------------------------------------------------------------------- + +; initialise next action/transmit bit + bsf NMRACTRL,NEXTACTION,0 + bsf NMRACTRL,TRANSMITBIT,0 + +; initialise TOTRACKBIT bitmask + movlw 0x80 + movwf TOTRACKBIT,0 ; make bit mask be 1000 0000 + +; initialise booster direction + bsf TRISC,0,0 ; make pin 0 (booster direction) output + bcf PORTC,0,0 ; set low initially + ; set booster pwm high bsf TRISC,1,0 ; make pin 1 (booster pwm) output bsf PORTC,1,0 ; booster pwm high -; *** also need to deal with initial short circuit state *** -; initialise booster direction - bsf TRISC,0,0 ; make pin 0 (booster direction) output +;----------------------------------------------------------------------------------------- -; initialise next action/transmit bit - bsf NMRACTRL,NEXTACTION,0 - bsf NMRACTRL,TRANSMITBIT,0 +; 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 + +; interrupt set-up for serial receive + bsf PIE1,5,0 ; enable USART receive interrupt (p85) + bsf IPR1,5,0 ; set to low-priority interrupt + +; interrupt set-up for timer0 interrupt p79/80 + bsf INTCON,5,0 ; enable timer0 interrupts + bcf INTCON2,2,0 ; timer0 overflow low priority ;***************************************************************************************** main_loop_led call led_green - call waiting - call led_black - call waiting - goto main_loop_led + goto main_loop_led ;***************************************************************************************** interrupt_high - call led_red - call waiting - retfie 1 + goto panic ;***************************************************************************************** @@ -158,10 +146,11 @@ interrupt_low goto serial_receive btfss INTCON,2,0 ; check whether timer0 interrupt set goto timer0_interrupt - call led_red - call waiting - call led_red - retfie 1 ; return from interrupt to main if spurious interrupt + goto panic + +; if 2 interrupts are set at once the 2nd will generate a new interrupt on leaving +; the interrupt routine + ;***************************************************************************************** @@ -171,18 +160,18 @@ serial_receive movwf FSR0H,0 ; set high byte of IND0 pointer movff RCREG,IND0 ; copy to received register incf FROMSERIAL,1,0 ; advance FROMSERIAL pointer by 1 byte - btfss RCREG,0,0 ; check if bit 0 is set + btfss RCREG,7,0 ; check if bit 7 is set call advance_write_buffer ; if so, move to next buffer - call led_red - call waiting - return + retfie 1 +; *** I *think* the interrupt bit is cleared by reading out of RCREG +; but this may be something to try in debugging if stuff doesn't work advance_write_buffer ; check if on 1st byte of new buffer anyway (i.e. last 4 bits = 0) - movff FROMSERIAL,W ; copy FROMSERIAL pointer location to W + movf FROMSERIAL,0,0 ; copy FROMSERIAL pointer location to W andlw 0xF ; investigate last 4 bits ; if zero (i.e. overflowed to next buffer), branch to overflow check @@ -195,7 +184,7 @@ advance_write_buffer movlw 0xF andwf FROMSERIAL,1,0 swapf FROMSERIAL,1,0 - + fromserial_overflow ; clear bit 6 (will set back to buffer 0 if has overflowed to 4) bcf FROMSERIAL,6,0 @@ -215,7 +204,7 @@ timer0_interrupt ; check next action - if 0, change to 1 and return btfsc NMRACTRL,NEXTACTION,0 goto toggle_output - bsf + bsf NMRACTRL,NEXTACTION,0 retfie 1 @@ -255,19 +244,14 @@ decide_next_bit read_from_buffer -; if no, find current to-track byte and bit -; (and TRANSMITBIT with 0x1) - - movff TOTRACKBIT,W,0 - andlw 0x1 +; if currently on bit 7, want to skip to bit 6 -; checking whether TRANSMITBIT (bit mask) is at bit 0 -; (i.e. whether andlw 0x1 is 1 (on bit 0) or 0 (not on bit 0) + btfss TOTRACKBIT,7,0 + rrncf TOTRACKBIT,1,0 ; rotate mask right - bnz advance_pointer - -; if not on bit 0 (i.e. if the and above results in 0), -; set na=cb=bit value, advance bit (i.e. rotate TRANSMITBIT left), return +; if not on bit 7 , +; set na=cb=bit value, advance bit (i.e. rotate TRANSMITBIT right), +; check if bit7, if so, advance byte, return movff TOTRACK,FSR1L ; set low byte of IND1 pointer movlw 5 @@ -281,35 +265,45 @@ read_from_buffer zero_bit_to_track bcf NMRACTRL,TRANSMITBIT,0 bcf NMRACTRL,NEXTACTION,0 - call advance_bit - retfie 1 + goto advance_bit one_bit_to_track bsf NMRACTRL,TRANSMITBIT,0 bsf NMRACTRL,NEXTACTION,0 - call advance_bit + goto advance_bit + + + +advance_bit +; rotate tranmitbit to next position + + rrncf TOTRACKBIT,1,0 ; rotate mask right + + btfss TOTRACKBIT,7,0 + call advance_pointer + retfie 1 advance_pointer -; if currently on the last bit of the byte (bit 0), then check whether it is 1 or 0 +; currently on bit 7 of the byte, after having read rest of byte to track; check whether it is 1 or 0 movff TOTRACK,FSR1L movlw 5 movwf FSR1H,0 movff INDF1,W,0 - andlw 0x1 + andlw 0x80 - bnz advance_write_buffer - bra advance_write_byte + bnz advance_read_buffer + bra advance_read_byte -advance_write_buffer +advance_read_buffer -; move pointer to next buffer byte 0 +; move pointer to next buffer ; check if on 1st byte of new buffer anyway (i.e. last 4 bits = 0) movff TOTRACK,W ; copy TOTRACK pointer location to W @@ -329,11 +323,6 @@ advance_write_buffer totrack_overflow ; clear bit 6 (will set back to buffer 0 if has overflowed to 4) bcf TOTRACK,6,0 - -; advance to bit7 - - movlw 0x1 - movwf TOTRACKBIT,0 ; write na=cb=1 and return @@ -341,15 +330,12 @@ totrack_overflow -advance_write_byte +advance_read_byte ; advance to next byte of buffer (increment TOTRACK) +; (will be on bit 7 at this point anyway so no need to change TOTRACKBIT) incf TOTRACK,1,0 -; advance to bit7 - - movlw 0x1 - movwf TOTRACKBIT,0 ; set na=cb=new bit value @@ -364,35 +350,9 @@ advance_write_byte -advance_bit -; rotate tranmitbit to next position - - rlncf TOTRACKBIT,1,0 ; rotate mask left - - - -; use rotate through carry? -; rotate mask register for anding? would also provide easy check for which bit I'm on -; use top bit for last byte? signed integer arithmetic possible (branch if -ve etc.) - - ;***************************************************************************************** -waiting -; change - timer0 now for NMRA timer; run this off timer0+counter - - bcf INTCON,2,0 ; clear timer0 interrupt bit (p109) - clrf TMR0H,0 ; p107 set high bit of timer0 to 0 (buffered, - ; so only actually set when write to tmr0l occurs) - clrf TMR0L,0 ; set low bit o timer0 - timer now set to 0000h -loop - btfss INTCON,2,0 ; check whethr tiomer0 interrupt has been set - - ; skip next instruction if so - bra loop - return - - led_green bcf TRISD,2,0 ; make pin RD2 an output (DS100) @@ -409,6 +369,14 @@ led_red return +panic + bcf INTCON,7,0 ; disable high-priority interrupts + bcf INTCON,6,0 ; disable low-priority interrupts + bcf PORTC,1,0 ; switch off booster +panic_loop + call led_red + goto panic_loop + ;***************************************************************************************** end