;*************************************************************************** ; Module name Chief_AVR.asm ;--------------------------------------------------------------------------- ; Author Reinhard Müller ;--------------------------------------------------------------------------- ; History 2005-12-11 to 2006-01-07 RM: Initial version. ; 2006-04-02 RM: Pull-ups disabled to be more sensitive ; 2006-04-08 RM: Pull-ups enabled again at Braunlage ; 2006-05-10 RM: bError replaced by bHold: Hold current switch ; state with conficting requests after switch ; change due to request from an inside sensor ; until all sensors released again. ; 2006-05-22 RM: bInside added to keep switch due to inside ; request info even if sensor is bouncing. ; In case of conflict, outside sensors have ; priority, don't switch on requests from ; both outside sensors. bHold is allways set ; on switch during conflicting requests. ; 2006-08-31 RM: Assignment of inside and outside sensors to ; top and bottom changed to be consistent ; with the drawings in the descriptions: ; Inside top, outside bottom. ;--------------------------------------------------------------------------- ; Description Chiefumschaltung ;*************************************************************************** #include #define DELAY1 20 // Time relay coil powered and gap between #define DELAY2 250 - 4 * DELAY1 // Time RS off - 4 * DELAY1 #define OCC_ON 3 // # of cycles for occupancy on #define OCC_OFF 200 // # of cycles for occupancy off #define PORT_IN PINC #define LEFT_I_B 3 // bit of J11 = PC3 = 26 Left top = inside #define LEFT_O_B 2 // bit of J12 = PC2 = 25 Left bottom = outside #define RIGHT_I_B 1 // bit of J13 = PC1 = 24 Right top = inside #define RIGHT_O_B 0 // bit of J14 = PC0 = 23 Right bottom = outside #define LEFT_IN (1< Init as no button pressed ; End of Init ;*************************************************************************** ; ******** Main ********* ; uses: r15 zero ; r16 time used for delay ; r19 temp used by delay ; r20 ucSensor ; r22 bLeft ; r23 bOld ; r24 bHold ; r25 bInside ;*************************************************************************** ; Read bLeft byte from EEPROM EEPROM_read: sbic EECR,EEWE ; Wait for completion of previous write rjmp EEPROM_read out EEARH,zero ; Set up address in address register out EEARL,zero ; only address 0 is used! sbi EECR,EERE ; Start eeprom read by writing EERE in bLeft,EEDR ; Read data from data register ; End of EEPROM_Read ldi bOld,3 ; bOld = 3 --> force setting of relais clr bHold ; bHold = FALSE ldi time,250 ; Delay value cbi PORT_LL,LED_L_OUT rcall Delay ; wait one second for detector internal sbi PORT_LL,LED_L_OUT cbi PORT_LL,LED_L_IN rcall Delay ; capacitors to charge up to avoide false sbi PORT_LL,LED_L_IN cbi PORT_RL,LED_R_IN rcall Delay ; occupancy status sbi PORT_RL,LED_R_IN cbi PORT_RL,LED_R_OUT rcall Delay sbi PORT_RL,LED_R_OUT cbi PORT_DL,LED_RIGHT cbi PORT_DL,LED_LEFT ; mark end of booting For_Ever: ;*************************************************************************** ; Debounce inputs ; uses: r15 zero constant ; r16 time used for delay ; r17 ucMask used by delay ; r18 current debounce counter used by delay ; r19 temp used by delay ; r20 ucSensor ; r21 ucInput ; r0 debounce counter 3 ; r1 debounce counter 2 ; r2 debounce counter 1 ; r3 debounce counter 0 ; r28/r29 debounce counter pointer ldi time,1 ; don't test more than once per ms rcall Delay .def Mask = r17 .def Counter = r18 ldi Mask,0x0F in Input,PORT_IN ; ucInput eor Input,Mask ; convert to active high eor Input,Sensor ; get changes and Input,Mask ; only lower 4 bits ldi Mask,0x08 ; ucMask ldi YL,0 ; load debounce counter base address ldi YH,0 ; Use registers 0 to 3 ; 20 Debounce_Next: mov temp,Input and temp,Mask ; ucInput & ucMask breq No_Change ld Counter,Y ; get debounce counter inc Counter mov temp,Sensor and temp,Mask ; ucSensor & ucMask brne Off_Time cpi Counter,OCC_ON+1 ; count for occupancy ON brsh Change_State Off_Time: cpi Counter,OCC_OFF+1 ; count for occupancy OFF brlo Bouncing Change_State: eor Sensor,Mask ; toggle sensor bit No_Change: ldi Counter,0 ; reset bounce counter Bouncing: st Y+,Counter ; save bounce counter & advance pointer lsr Mask ; mask next bit brne Debounce_Next ; 10-20 -> 79 max ; 19 for bouncing ON ; 18 for bouncing OFF ; End of Debounce ;*************************************************************************** ; Copy sensor status to individual LEDs ldi Mask,0x0F eor Sensor,Mask ; green LEDs active low in temp,PORT_LL ; LED_L_OUT / LED_L_IN port bst Sensor,LEFT_O_B bld temp,LED_L_OUT bst Sensor,LEFT_I_B bld temp,LED_L_IN out PORT_LL,temp in temp,PORT_RL ; LED_R_OUT / LED_R_IN port bst Sensor,RIGHT_O_B bld temp,LED_R_OUT bst Sensor,RIGHT_I_B bld temp,LED_R_IN out PORT_RL,temp eor Sensor,Mask ; restore Sensor byte ; 15 .undef Mask .undef Counter ;*************************************************************************** ; Test for switch condition mov temp,Sensor andi bLeft,0x01 ; check where we are (test bit 0 only) breq Test_Right andi temp,RIGHT ; test for "other" request breq No_Request ; No request from other side ldi temp,LEFT rjmp Test_Both Test_Right: andi temp,LEFT ; test for "other" request breq No_Request ; No request from other side ldi temp,RIGHT Test_Both: and temp,Sensor breq Switch ; Normal switch condition ; 11 ; Request from both sides! Both_Sides: sbi PORT_RLY,BUZZER ; ALARM!!! mov temp,Sensor andi temp,OUTSIDE breq Inside_only ; Requests from inside only ; Conflict includes request from outside ; Outside sensor have priority! andi bLeft,0x01 ; check where we are (test bit 0 only) breq Test_R_Out sbrs Sensor,RIGHT_O_B ; test for "other" request rjmp Check_Switch ; No request from other side -> stay sbrs Sensor,LEFT_O_B rjmp Switch_Conf ; Switch and set bHold rjmp Check_Switch ; Request from both outside sensors -> stay Test_R_Out: sbrs Sensor,LEFT_O_B ; test for "other" request rjmp Check_Switch ; No request from other side -> stay sbrs Sensor,RIGHT_O_B rjmp Switch_Conf ; Switch and set bHold rjmp Check_Switch ; Request from both outside sensors -> stay Inside_only: tst bHold brne Check_Switch ; bHold set: don't switch Switch_Conf: com bLeft ; bLeft = !bLeft --> switch to other side ldi bHold,0xFF ; bHold = TRUE as switch during conflict rjmp Check_Switch ; 15 max ; Normal switch condition detected Switch: com bLeft ; bLeft = !bLeft --> switch to other side ldi bInside,0x00 mov temp,Sensor andi temp,INSIDE breq No_Request ; No request from inside ldi bInside,0xFF ; Switch due to inside request: ; No switch request condition No_Request: sbrs bInside,0 ; bInside set? rjmp Clr_Alarm mov temp,Sensor ; and an inside request? andi temp,INSIDE breq Test_Outside ldi bHold,0xFF ; --> bHold = TRUE rjmp Clr_Alarm Test_Outside: mov temp,Sensor ; and outside request only? andi temp,OUTSIDE breq Clr_Alarm ldi bInside,0x00 ; clear bInside on outside request only Clr_Alarm: cbi PORT_RLY,BUZZER ; Shut up! tst Sensor brne Check_Switch ; clear bHold if no request at all clr bHold ; bHold = FALSE ; 20 if switch ; 14 if no switch ;*************************************************************************** ; check for side switch Check_Switch: andi bLeft,0x01 ; reduce to bit 0 cp bOld,bLeft ; bLeft == bOld ? breq Go_For_Ever ; no side switch ; --> 20+79+15+7+14+3=138 ; --> 20+79+15+11+20+3=148 sbi PORT_RLY,RS_OFF ; start with switching RS off ; Write bLeft byte to EEPROM EEPROM_write: sbic EECR,EEWE ; Wait for completion of previous write rjmp EEPROM_write out EEARH,zero ; Set up address (temp:temp) in address register out EEARL,zero ; only address 0 is used! out EEDR,bLeft ; Write data (bLeft) to data register cli ; Disable IRQs sbi EECR,EEMWE ; Write logical one to EEMWE sbi EECR,EEWE ; Start eeprom write by setting EEWE sei ; Enable IRQs ; End of EEPROM_write ; 9 --> 157 max. between calls to Delay ldi time,DELAY1 ; set delay time rcall Delay tst bLeft breq Set_Right ; set to left side cbi PORT_DL,LED_RIGHT sbi PORT_RLY,TRK_LEFT rcall Delay cbi PORT_RLY,TRK_LEFT rcall Delay sbi PORT_RLY,LN_LEFT rcall Delay cbi PORT_RLY,LN_LEFT sbi PORT_DL,LED_LEFT rjmp Wait_RS_on ;set to right side Set_Right: cbi PORT_DL,LED_LEFT sbi PORT_RLY,TRK_RIGHT rcall Delay cbi PORT_RLY,TRK_RIGHT rcall Delay sbi PORT_RLY,LN_RIGHT rcall Delay cbi PORT_RLY,LN_RIGHT sbi PORT_DL,LED_RIGHT Wait_RS_on: ldi time,DELAY2 ; set delay time rcall Delay cbi PORT_RLY,RS_OFF mov bOld,bLeft ; bOld = bLeft; Go_For_Ever: rjmp For_Ever