; CC5X Version 3.4, Copyright (c) B Knudsen Data ; C compiler for the PICmicro family ; ************ 24. Jun 2009 9:07 ************* processor 16C54 radix DEC TMR0 EQU 0x01 PORTA EQU 0x05 PORTB EQU 0x06 Carry EQU 0 Zero_ EQU 2 key EQU 0 PIN1 EQU 0 PIN2 EQU 1 previousTMR0 EQU 0x09 subClock EQU 0x0A timer1 EQU 0x0B timer2L EQU 0x0C timer2H EQU 0x0D timeout1 EQU 0 timeout2 EQU 1 state1 EQU 0x0F state2 EQU 0x10 keyState EQU 2 sample EQU 0x07 incr EQU 0x08 ; FILE test\state.c ;/* ; STATE MACHINES AND SOFTWARE TIMERS ; ================================== ; ; State machines are useful when many signals have to ; be handled independent. ; ; STATE MACHINE 1: ; key debouncing: key accepted when stable for 50 ; millisec. ; ; STATE MACHINE 2: ; generates a pattern on PIN 1 and PIN 2 when key ; is pressed: ; ; PIN 1: |^^^^^^^^^^^^^^^^^|__________ _ _ _ _ ; ; PIN 2: _______|^^^^^|_______________ _ _ _ _ ; ; | | | | | ; 0 60 100 130 500 millisec. ; ; SOFTWARE TIMERS: ; timer 1 is assigned to finite state machine 1 ; timer 2 is assigned to finite state machine 2 ; ; Note: The timing assumes a 4 MHz oscillator ;*/ ; ;/* IO-CONFIGURATION: */ ;#define Konfig_portA 0x01 /* xxxx 0001, 0=Output */ ;#define Init_portA 0x00 /* 0000 0000 */ ; ;#define Konfig_portB 0x00 /* 0000 0000, 0=Output */ ;#define Init_portB 0x00 /* 0000 0000 */ ;/* ; Port I/O Name ; ; A.0 I key ; A.1 O - ; A.2 O - ; A.3 O - ; ; B.0 O PIN1 ; B.1 O PIN2 ; B.2 O - ; B.3 O - ; B.4 O - ; B.5 O - ; B.6 O - ; B.7 O - ;*/ ;#pragma bit key @ PORTA.0 ;#pragma bit PIN1 @ PORTB.0 ;#pragma bit PIN2 @ PORTB.1 ; ;#define Delay_1 ( 60 - 0 ) ;#define Delay_2 (100 - 60) ;#define Delay_3 (130 - 100) ;#define Delay_4 (500 - 130) ; ;#define OPEN 1 ;#define PRESSING 2 ;#define PRESSED 3 ;#define OPENING 4 ; ;#define READY 1 ;#define STEP1 2 ;#define STEP2 3 ;#define STEP3 4 ;#define STEP4 5 ; ;char previousTMR0, subClock; ;char timer1, timer2L, timer2H; ;bit timeout1, timeout2; ;char state1, state2; ;bit keyState; ; ;void timerTick( void) ;/* ; - decrements active timers ; - 4 MHz oscillator ; - period: 1 millisec. (prescaler divide by 8) ; - subClock: 0 .. 125 ;*/ ;{ timerTick ; char sample, incr; ; ; sample = TMR0; /* sampling the timer */ MOVF TMR0,W MOVWF sample ; incr = sample - previousTMR0; MOVF previousTMR0,W SUBWF sample,W MOVWF incr ; previousTMR0 = sample; MOVF sample,W MOVWF previousTMR0 ; ; subClock -= incr; MOVF incr,W SUBWF subClock,1 ; ; if ( !Carry) { BTFSC 0x03,Carry GOTO m002 ; /* new 1 millisec. tick */ ; subClock += 125; MOVLW 125 ADDWF subClock,1 ; ; if ( !timeout1) { BTFSC 0x0E,timeout1 GOTO m001 ; timer1 -= 1; DECF timer1,1 ; if ( timer1 == 255) INCF timer1,W BTFSC 0x03,Zero_ ; timeout1 = 1; BSF 0x0E,timeout1 ; } ; if ( !timeout2) { m001 BTFSC 0x0E,timeout2 GOTO m002 ; if ( -- timer2L == 255) { DECF timer2L,1 INCFSZ timer2L,W GOTO m002 ; if ( -- timer2H == 255) DECF timer2H,1 INCF timer2H,W BTFSC 0x03,Zero_ ; timeout2 = 1; BSF 0x0E,timeout2 ; } ; } ; } ;} m002 RETLW 0 ; ;#define startTimer1( count) { \ ; timer1 = count; \ ; timeout1 = 0; \ ;} ; ;#define startTimer2( count) { \ ; timer2L = (count) % 256; \ ; timer2H = (count) / 256; \ ; timeout2 = 0; \ ;} ; ;void fsm1( void) ;{ fsm1 ; switch ( state1) { /* state machine 1 */ MOVF state1,W XORLW 1 BTFSC 0x03,Zero_ GOTO m003 XORLW 3 BTFSC 0x03,Zero_ GOTO m004 XORLW 1 BTFSC 0x03,Zero_ GOTO m006 XORLW 7 BTFSC 0x03,Zero_ GOTO m007 GOTO m009 ; case OPEN: ; if ( key) { m003 BTFSS 0x05,key GOTO m009 ; startTimer1( 50); MOVLW 50 MOVWF timer1 BCF 0x0E,timeout1 ; state1 = PRESSING; MOVLW 2 MOVWF state1 ; } ; break; GOTO m009 ; ; case PRESSING: ; if ( key == 0) m004 BTFSC 0x05,key GOTO m005 ; state1 = OPEN; MOVLW 1 MOVWF state1 ; else if ( timeout1) { GOTO m009 m005 BTFSS 0x0E,timeout1 GOTO m009 ; keyState = 1; BSF 0x0E,keyState ; state1 = PRESSED; MOVLW 3 MOVWF state1 ; } ; break; GOTO m009 ; ; case PRESSED: ; if ( key == 0) { m006 BTFSC 0x05,key GOTO m009 ; startTimer1( 50); MOVLW 50 MOVWF timer1 BCF 0x0E,timeout1 ; state1 = OPENING; MOVLW 4 MOVWF state1 ; } ; break; GOTO m009 ; ; case OPENING: ; if ( key) m007 BTFSS 0x05,key GOTO m008 ; state1 = PRESSED; MOVLW 3 MOVWF state1 ; else if ( timeout1) { GOTO m009 m008 BTFSS 0x0E,timeout1 GOTO m009 ; keyState = 0; BCF 0x0E,keyState ; state1 = OPEN; MOVLW 1 MOVWF state1 ; } ; break; ; } ;} m009 RETLW 0 ; ;void fsm2( void) ;{ fsm2 ; switch ( state2) { /* state machine 2 */ MOVF state2,W XORLW 1 BTFSC 0x03,Zero_ GOTO m010 XORLW 3 BTFSC 0x03,Zero_ GOTO m011 XORLW 1 BTFSC 0x03,Zero_ GOTO m012 XORLW 7 BTFSC 0x03,Zero_ GOTO m013 XORLW 1 BTFSC 0x03,Zero_ GOTO m014 GOTO m015 ; case READY: ; if ( keyState == 1) { m010 BTFSS 0x0E,keyState GOTO m015 ; PIN1 = 1; BSF 0x06,PIN1 ; startTimer2( Delay_1); MOVLW 60 MOVWF timer2L CLRF timer2H BCF 0x0E,timeout2 ; state2 = STEP1; MOVLW 2 MOVWF state2 ; } ; break; GOTO m015 ; ; case STEP1: ; if ( timeout2) { m011 BTFSS 0x0E,timeout2 GOTO m015 ; PIN2 = 1; BSF 0x06,PIN2 ; startTimer2( Delay_2); MOVLW 40 MOVWF timer2L CLRF timer2H BCF 0x0E,timeout2 ; state2 = STEP2; MOVLW 3 MOVWF state2 ; } ; break; GOTO m015 ; ; case STEP2: ; if ( timeout2) { m012 BTFSS 0x0E,timeout2 GOTO m015 ; PIN2 = 0; BCF 0x06,PIN2 ; startTimer2( Delay_3); MOVLW 30 MOVWF timer2L CLRF timer2H BCF 0x0E,timeout2 ; state2 = STEP3; MOVLW 4 MOVWF state2 ; } ; break; GOTO m015 ; ; case STEP3: ; if ( timeout2) { m013 BTFSS 0x0E,timeout2 GOTO m015 ; PIN1 = 0; BCF 0x06,PIN1 ; startTimer2( Delay_4); MOVLW 114 MOVWF timer2L MOVLW 1 MOVWF timer2H BCF 0x0E,timeout2 ; state2 = STEP4; MOVLW 5 MOVWF state2 ; } ; break; GOTO m015 ; ; case STEP4: ; if ( timeout2) m014 BTFSS 0x0E,timeout2 GOTO m015 ; state2 = READY; MOVLW 1 MOVWF state2 ; break; ; } ;} m015 RETLW 0 ; ;void main ( void) ;{ main ; /* initialize */ ; PORTA = Init_portA; CLRF PORTA ; TRISA = Konfig_portA; MOVLW 1 TRIS PORTA ; PORTB = Init_portB; CLRF PORTB ; TRISB = Konfig_portB; MOVLW 0 TRIS PORTB ; timeout1 = 1; BSF 0x0E,timeout1 ; timeout2 = 1; BSF 0x0E,timeout2 ; state1 = READY; MOVLW 1 MOVWF state1 ; state2 = OPEN; MOVWF state2 ; keyState = 0; BCF 0x0E,keyState ; OPTION = 2; /* prescaler divide by 8 */ MOVLW 2 OPTION ; ; while (1) { ; timerTick(); /* decrement timers */ m016 CALL timerTick ; /* Not more than 1 (2) millisec. ; between each call to timerTick() */ ; ; /* .. sample analog channels */ ; /* .. do other IO communication */ ; /* .. do global processing and testing */ ; fsm1(); CALL fsm1 ; fsm2(); CALL fsm2 ; /* next loop */ ; } GOTO m016 ORG 0x01FF GOTO main END ; *** KEY INFO *** ; 0x0000 29 word(s) 5 % : timerTick ; 0x001D 52 word(s) 10 % : fsm1 ; 0x0051 63 word(s) 12 % : fsm2 ; 0x0090 18 word(s) 3 % : main ; RAM usage: 10 bytes (2 local), 15 bytes free ; Maximum call level: 1 ; Total of 163 code words (31 %)