; ; SHBoost ; DCC controller for SHMDBoost ; created 12/06/98 ; V 0.1 initial verison ; V 0.2 1/23/99 relaxed sense error sensitivity due to Bodman report of Mathias #DEFINE P16x #IFNDEF P16x processor 12C508 __CONFIG _CP_OFF & _MCLRE_OFF & _WDT_ON & _IntRC_OSC include SER1 EQU H'0000' SER2 EQU H'0001' #define SER_DAT1 GPIO,SER1 ; data input #define SER_DAT2 GPIO,SER2 ; data input #define ENABLE GPIO,0x0002 ; L6203 enable output #define SENSE GPIO,0x0003 ; current sense input #define LED_RED GPIO,0x0004 ; LED, red #define LED_GREEN GPIO,0x0005 ; LED, green #ELSE processor 16C84 __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_ON & _HS_OSC __IDLOCS 0002 ; ID- information in EPROM include SER1 EQU H'0000' SER2 EQU H'0001' #define SER_DAT1 PORTB,SER1 ; RB0,data input #define SER_DAT2 PORTB,SER2 ; RB1,data input #define ENABLE PORTB,0x0002 ; RB2,L6203 enable output #define SENSE PORTB,0x0003 ; RB3,current sense input #define LED_RED PORTB,0x0004 ; RB4,LED, red #define LED_GREEN PORTB,0x0005 ; RB5,LED, green #ENDIF ; cblock 0x0007 ; !!!!!!! aendern fuer 12x cblock 0x000c ; !!!!!!! aendern fuer 16x flags store_gpio ser_changed SER1_INACTIVE SER2_INACTIVE temp temp2 nmb_short_try ; how often are we allowed to try to apply ; power to track ? (counts down from 7 to 1) retry_delay ; number of timer0 ovl to wait to apply power to track sense_wait ; number of timer0 ovl to wait to remove power due to ; sense error endc #define rs_err flags,0 #define sense_err flags,1 #define sense_cntr 3 ; how often has sense to be active before removing power READPORT MACRO #IFNDEF P16x movf GPIO,w #ELSE movf PORTB,w #ENDIF endm #IFDEF P16x bank_0 MACRO bcf STATUS,RP0 ENDM bank_1 MACRO bsf STATUS,RP0 ENDM #ENDIF led_ok MACRO bcf LED_RED bsf LED_GREEN ENDM led_rserr MACRO bsf LED_RED bsf LED_GREEN ENDM led_sense MACRO bsf LED_RED bcf LED_GREEN ENDM ;************************************************************** org 0x0000 #IFNDEF P16x movwf OSCCAL ; calibrate internal oscillator #ENDIF movlw 0x0b; ; initialize TRIS #IFNDEF P16x tris GPIO #ELSE bank_1 movwf TRISB bank_0 #ENDIF led_rserr ; initialize ports, show rs error bcf ENABLE ; be silent at first clrf ser_changed ; clear ser_changed register READPORT ; test whether pulses on both rs lines andlw 0x03 movwf store_gpio no_rs READPORT ; test whether rs lines change andlw 0x03 movwf temp ; store port xorwf store_gpio,w btfsc STATUS,Z goto no_rs iorwf ser_changed,f ; test whether both rs lines change movlw 0x03 subwf ser_changed,w btfss STATUS,Z goto no_rs movf temp,w movwf store_gpio ; store gpio status led_ok ; switch RSERR LED off bcf sense_err ; clear sense_err flag movlw D'10' movwf SER1_INACTIVE ; initialize idle counters movwf SER2_INACTIVE ; clrf retry_delay movlw 0x7 movwf nmb_short_try movlw sense_cntr movwf sense_wait movlw (D'255' - D'13'); initialize timer to 62 usec movwf TMR0 #IFNDEF P16x movlw 0x91 ; enable pull-up, clock on internal clock, scale by 4 option #ELSE movlw 0x51 ; portb pull-up, clock on internal clock, scale by 4 bank_1 movwf OPTION_REG bank_0 #ENDIF loopidle bsf ENABLE ; apply power to track bcf sense_err ; clear sense_err flag led_ok loop clrwdt wait_t movf TMR0,w btfss STATUS,Z goto wait_t movlw (D'255' - D'13'); initialize timer to 62 usec movwf TMR0 ;*********************** test railsync lines ************************************* READPORT ; test whether serx_dat changes andlw 0x03 movwf temp xorwf store_gpio,w movwf ser_changed movf temp,w movwf store_gpio bcf rs_err ; clear rs_err flag movlw D'10' ; test whether ser1_dat changes btfsc ser_changed,SER1 movwf SER1_INACTIVE ; yes, reset idle count movf SER1_INACTIVE,F btfsc STATUS,Z ; is idle count zero ? goto rs1_err ; yes decf SER1_INACTIVE,F ; no, decrement idle counter goto t2 rs1_err bsf rs_err t2 movlw D'10' ; test whether ser2_dat changes btfsc ser_changed,SER2 movwf SER2_INACTIVE ; yes, reset idle count movf SER2_INACTIVE,F btfsc STATUS,Z ; is idle count zero ? goto rs2_err ; yes decf SER2_INACTIVE,f ; no, decrement idle counter goto rs_exit rs2_err bsf rs_err ; yes, set rs_err flag rs_exit btfss rs_err goto tsense bcf ENABLE led_rserr goto loop ;*********************** test sense line ************************************* ; test whether output short tsense btfsc SENSE ; check SENSE line goto sense_ok ; everything OK btfsc sense_err ; already sense_err detected ? goto pwr_off ; yes, don't wait decfsz sense_wait,f ; decrement sense_wait cntr goto arm_sns_err ; not zero, then wait pwr_off bcf ENABLE ; remove power at once movlw (D'255' - D'250'); set timer to 1.2 ms movwf TMR0 led_sense bsf sense_err movlw 1 movwf sense_wait movf nmb_short_try,w ; calculate delay time movwf temp ; retry_delay = 0x800 >> nmb_short_try clrf temp2 bsf STATUS,C rol rrf temp2,f decfsz temp,f goto rol movf temp2,w movwf retry_delay ; set retry delay movlw 0x01 ; stretch retry delay decfsz nmb_short_try,f ; by decrementing nmb_short_try goto loopsns movwf nmb_short_try ; don't go below 1 loopsns clrwdt wait_t2 movf TMR0,w btfss STATUS,Z goto wait_t2 movlw (D'255' - D'250'); initialize timer to 1.2 msec movwf TMR0 decfsz retry_delay,f ; wait until it's time goto loopsns ; now it's time retry movlw (D'255' - D'13'); initialize timer to 62 usec movwf TMR0 goto loopidle arm_sns_err movlw 0x7 ; reset nmb_short_try movwf nmb_short_try goto loopidle sense_ok movlw sense_cntr movwf sense_wait bcf sense_err ; clear sense_err flag movlw 0x7 ; reset nmb_short_try movwf nmb_short_try goto loopidle end