//====================================================== // (c)2008-9 Matthew Ford // Forward Computing and Control Pty. Ltd. // www.forward.com.au // All rights reserved // // You may freely copy and distribute this program for // commercial and non-commercial use provided:- // i) this copyright notice remains attached // ii) you clearly mark any changes you make to the code //====================================================== // // 3LevelDriver.asm // // Main: ATtiny84 // mode: ISP mode // // Program: ATtiny84 // Flash - Input HEX File: yourdir/ThreeLevelDriver.hex // EEPROM - not used // // Fuses: // SPIEN ticked // BODLEVEL Brown Out detection at VCC = 1.8V // CKDIV8 ticked // SUT_CKSEL Int RC Osc. 8Mhz; .... 6CK/14CK +64mS // Auto Read ticked // Smart Warnings ticked // Verify After programming ticked // then Progam the fuses // // LockBits: // LB no lock features enabled // // Advanced: // Calibrate of frequency 8.0Mhz // Do Not write any value to the Cal byte. startup handles this // // HW Setting // VTarget 5.1 // VREF 5.1 (not used) // Clock Generator 3.686Mhz (max) // // Auto: // Erase Device // Check Signature // Program FLASH // Verify FLASH //--------------------------------------------------------- .include "tn84def.inc" // start interrupt routine .macro SAVE_SREG push Temp in Temp, SREG // save the SREG push Temp .ENDMACRO // end interrupt routine .macro RESTORE_SREG pop Temp out SREG, Temp // restore the SREG pop Temp .ENDMACRO .equ NO_GLOBAL_VARS = 0 // number of globals available .equ CURRENT_SP_HIGH = 1000 // the current setpoint, 1000 = full scale current, approx 500mA .equ CURRENT_SP_MED = 333 // the current setpoint, 333 = approx 167mA .equ CURRENT_SP_LOW = 111 // the current setpoint, 111 = approx 55mA .equ SW_B = PB1 // define name for switch input pin .equ uC_OUTPUT_B = PB0 // define name for uC output pin .def Temp = r16// Temporary register //------------------------------------------------ // TRIGGER_Flags Flags set for triggers // This register is updated by both interrupts and main code //------------------------------------------------ .def TRIGGER_Flags = r17 // initially 0 no triggers set .equ TRIGGER_SwitchChanged = 0 // bit0, 1 if switch just changed else 0 .equ TRIGGER_Timer1 = 1 // set by 2mS Timer1 // Debounce Counter Counts allows up to 0.5sec debounce = 250 count .def DEBOUNCE_Counter = r18 // count debounce timeout .equ Debounce_Count_Low = 5 // about 0.01 sec = 5 x 2mS .equ Debounce_Count_High = 5 // about 0.01 sec = 5 x 2mS // increase the appropiate count if you switch needs a longer debouce in one direction //------------------------------------------------ //SW_Flags, Holds the current debounced switch state and last state and change trigger //------------------------------------------------ .def SW_Flags = r19 // 0b00000000 initially i.e. Switch up and last switch up .equ SW_SWDown = 0 // bit0, 1 if button pressed, 0 if button released. .equ SW_SWLastInput = 1 // bit1, 1 if last read SW pressed (low) not debounced //------------------------------------------------ //------------------------------------------------ //New_Torch_State, Holds the new state of the torch // updated from current Torch_State by triggers //------------------------------------------------ .def New_Torch_State = r20 //------------------------------------------------ //Torch_State, Holds the current state of the torch //------------------------------------------------ .def Torch_State = r21 // initially 0 == off .equ Torch_State_OFF = 0 // the torch state constants .equ Torch_State_LOW = Torch_State_OFF+1 // 1 .equ Torch_State_MED = Torch_State_LOW+1 // 2 .equ Torch_State_HIGH = Torch_State_MED+1 // 3 .equ Torch_State_EXCEEDED = Torch_State_HIGH+1 // 4 first invalid state // registers to hold current setpoint .def SP_High = r22 // holds the high byte of the setpoint current .def SP_Low = r23 // holds the low byte of the setpoint current .def ADCLow = r24 // low byte of adc .def ADCHigh = r25 // high byte of adc ; ***** INTERRUPT VECTORS ************************** .org 0x0000 rjmp RESET .org OC1Aaddr // = 0x0006 TIMER1 COMPARE A MATCH rjmp TIMER1_COMPARE_A_INT //------------------------------------- // ADC interrupt, result available // removed this interrupt // just check if conversion start still set. //------------------------------------- //--------------------------------------------- // Main code // Program starts here //--------------------------------------------- RESET: cli // disable interrupts // set clock to 8Mhz i.e. remove div8 that is set by programmer ldi Temp, (1<= setpoint (signed comparison) // else ADC < setpoint CURRENT_LOW: // ADC < setpoint ==> make output high sbi PORTB, uC_OUTPUT_B // set output high rjmp END_LED_CONTROL CURRENT_HIGH: // ADC > setpoint ==> make output low cbi PORTB, uC_OUTPUT_B // set output low rjmp END_LED_CONTROL // all paths jmp to here END_LED_CONTROL: ret //------------------------------- //-------------------------- // TIMER1_2mS // called each main loop // but only called Switch_Debounce if trigger // has been set by timer interrupt //------------------------- TIMER1_2mS: sbrs TRIGGER_Flags, TRIGGER_Timer1 rjmp END_TIMER1_2mS // else changed clear trigger now cbr Trigger_Flags, (1< off PROCESS_SWDown_TRIGGER_TORCH_HIGH: // high -> off ldi New_TORCH_State, Torch_State_OFF rjmp END_PROCESS_SWDown_TRIGGER PROCESS_SWDown_TRIGGER_TORCH_OFF: // off -> low ldi New_TORCH_State, Torch_State_LOW rjmp END_PROCESS_SWDown_TRIGGER PROCESS_SWDown_TRIGGER_TORCH_LOW: // low -> med ldi New_TORCH_State, Torch_State_MED rjmp END_PROCESS_SWDown_TRIGGER PROCESS_SWDown_TRIGGER_TORCH_MED: // med -> high ldi New_TORCH_State, Torch_State_HIGH // rjmp END_PROCESS_SWDown_TRIGGER drop through END_PROCESS_SWDown_TRIGGER: ret //------------------------------------- //------------------------------------- //UPDATE_TORCH_STATE // Set the new torch state and load current setpoint //------------------------------------- UPDATE_TORCH_STATE: mov TORCH_State, New_TORCH_State // update state to new state rcall LOAD_CURRENT_SETPOINT // load new setpoint ret //------------------------------------- //------------------------------------- //LOAD_CURRENT_SETPOINT // Loads the current setpoint base on the torch state // Also set SW_LedOn depending on TORCH_State //------------------------------------- LOAD_CURRENT_SETPOINT: cpi TORCH_State, Torch_State_OFF breq SET_TORCH_OFF // else cpi TORCH_State, TORCH_State_LOW breq SET_TORCH_LOW // else cpi TORCH_State, TORCH_State_MED breq SET_TORCH_MED // else cpi TORCH_State, TORCH_State_HIGH breq SET_TORCH_HIGH INVALID_STATE: // else invalid turn off ldi TORCH_State, TORCH_State_OFF // set valid state // drop through to set off SET_TORCH_OFF: clr SP_High clr SP_Low rjmp END_LOAD_CURRENT_SETPOINT SET_TORCH_LOW: ldi SP_High, high(CURRENT_SP_LOW) ldi SP_Low, low(CURRENT_SP_LOW) rjmp END_LOAD_CURRENT_SETPOINT SET_TORCH_MED: ldi SP_High, high(CURRENT_SP_MED) ldi SP_Low, low(CURRENT_SP_MED) rjmp END_LOAD_CURRENT_SETPOINT SET_TORCH_HIGH: ldi SP_High, high(CURRENT_SP_HIGH) ldi SP_Low, low(CURRENT_SP_HIGH) rjmp END_LOAD_CURRENT_SETPOINT END_LOAD_CURRENT_SETPOINT: ret //-------------------------------------