;********************************************************************** ; Dimmable LED light controller * ; For PIC16F627A * ; Uses the 4mhz internal oscillator * ; Copyright (c) Michael Nixon (zipplet) 2009. * ;********************************************************************** ; * ; Filename: ledlight.asm * ; Date: 01/03/09 * ; File Version: 0.1 * ; * ; Author: Michael Nixon (zipplet) * ; * ; * ;********************************************************************** ; * ; Files required: * ; * ; * ; * ;********************************************************************** ; * ; Notes: Internal oscillator at 4mhz. * ; The brightness of the light is controlled by PWM. * ; * ; RB0 is the status LED * ; RB3 is the light control pin * ; RA0 is the power button * ; RA1 is the down button * ; RA2 is the up button * ; * ;********************************************************************** errorlevel -305 errorlevel -302 errorlevel -205 list p=16f627a ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF ; '__CONFIG' directive is used to embed configuration data within .asm file. ; The lables following the directive are located in the respective .inc file. ; See respective data sheet for additional information on configuration word. ;***** PIN CONSTANTS #define LED_STATUS 0 #define LED_POWER 3 #define BUTTON_POWER 0 #define BUTTON_DOWN 1 #define BUTTON_UP 2 ;***** VARIABLE DEFINITIONS ; all of these are in the shared 16 bytes across all pages! w_temp EQU 0x70 ; variable used for context saving status_temp EQU 0x71 ; variable used for context saving fsr_temp EQU 0x72 ; variable used for context saving CBLOCK 0x20 ; === PAGE 0 === brset ; brightness setting a ; temporary counter i ; temporary counter ta ; temporary counter tb ; temporary counter buttons ; Buttons poweron ; power on ENDC ;********************************************************************** ORG 0x000 ; processor reset vector goto main ; go to beginning of program ;********************************************************************** ; main code ;********************************************************************** main banksel CMCON movlw 0x07 movwf CMCON ; comparators off clrf PORTA ; clear porta clrf PORTB ; clear portb banksel TRISA movlw b'00000111' ; buttons digital inputs movwf TRISA clrf TRISB ; portb all digital outputs ; Setup PWM banksel PR2 movlw .254 ; Period - timer resets at this value movwf PR2 banksel CCP1CON clrf CCPR1L ; Duty - 255 = full on ;movlw b'00000110' ; Timer 2 on, prescale 1:1 movlw b'00000100' ; Timer 2 on, prescale 1:1 movwf T2CON ; Timer 2 control movlw b'00001100' ; CCP1 = PWM movwf CCP1CON ; CCPR1L controls the duty cycle. When the timer counter is ; greater than this the output is off. ; 0 = off (no PWM) ; 1 = dimmest (PWM) ; 255 = 100% brightness (no PWM) ; We begin with the default brightness as full brightness banksel brset movlw 6 movwf brset clrf poweron ; ... but we begin with the light turned off movlw 0 call setbrightness ; Main loop mainloop ; Read buttons banksel PORTA ; Check for power button btfss PORTA, BUTTON_POWER goto power_not_pressed ; Debounce button by only allowing us to continue if it is held ; for 256 cycles. movlw .255 movwf i power_loop btfss PORTA, BUTTON_POWER goto power_not_pressed decfsz i goto power_loop ; --------------------------------------------- ; Power button function ; --------------------------------------------- movfw poweron skpz goto power_was_on ; Power was off. ; Check for "down" button at same time, if so then switch on ; at lowest brightness. movlw .1 btfsc PORTA, BUTTON_DOWN movwf brset ; Check for "up" button at same time, if so then switch on ; at highest brightness. movlw .6 btfsc PORTA, BUTTON_UP movwf brset movfw brset movwf poweron call setbrightness goto power_wait power_was_on ; Power was on, so turn it off clrf poweron movlw .0 call setbrightness power_wait bsf PORTB, LED_STATUS ; Wait for button to be released before continuing btfsc PORTA, BUTTON_POWER goto power_wait ; Wait 256 cycles call wait256 bcf PORTB, LED_STATUS power_not_pressed ; If power is off we just cycle movfw poweron skpnz goto mainloop ; Check for up button btfss PORTA, BUTTON_UP goto up_not_pressed ; Debounce button by only allowing us to continue if it is held ; for 256 cycles. movlw .255 movwf i up_loop btfss PORTA, BUTTON_UP goto up_not_pressed decfsz i goto up_loop ; --------------------------------------------- ; Up button function ; --------------------------------------------- ; First check if we are already at the highest (6) movlw .6 subwf brset, w skpnz goto up_wait ; Exit if already highest incf brset movfw brset call setbrightness up_wait bsf PORTB, LED_STATUS ; Wait for button to be released before continuing btfsc PORTA, BUTTON_UP goto up_wait ; Wait 256 cycles call wait256 bcf PORTB, LED_STATUS up_not_pressed ; Check for down button btfss PORTA, BUTTON_DOWN goto down_not_pressed ; Debounce button by only allowing us to continue if it is held ; for 256 cycles. movlw .255 movwf i down_loop btfss PORTA, BUTTON_DOWN goto down_not_pressed decfsz i goto down_loop ; --------------------------------------------- ; Up button function ; --------------------------------------------- ; First check if we are already at the lowest (1) movlw .1 subwf brset, w skpnz goto down_wait ; Exit if already lowest decf brset movfw brset call setbrightness down_wait bsf PORTB, LED_STATUS ; Wait for button to be released before continuing btfsc PORTA, BUTTON_DOWN goto down_wait ; Wait 256 cycles call wait256 bcf PORTB, LED_STATUS down_not_pressed goto mainloop ;********************************************************************** ; Big delay ;********************************************************************** wait256 movlw 0xFF movwf ta movlw 0xFF movwf tb decfsz ta goto $-1 decfsz tb goto $-3 return ;wait256 ;movlw .255 ;movwf i ;wait256loop ;decfsz i ;goto wait256loop ;return ;********************************************************************** ; Set brightness of the light from table (use W) ; 0 = off ; 1 - 5 = dimmed levels ; 6 = fully on ;********************************************************************** setbrightness call table_brightness banksel CCPR1L movwf CCPR1L bcf CCP1CON, 5 bcf CCP1CON, 4 banksel poweron movfw poweron skpz bsf CCP1CON, 4 return ;********************************************************************** ; Data tables ; Note because the data tables use computed GOTOs we *must* set PCLATH ; (upper bits of address to be loaded into PC) to the address of the ; table before addwf, or the PIC will crash horribly. ;********************************************************************** org 0x100 table_brightness movwf ta ; save W (index to table) movlw HIGH table_brightness ; get high addr into W movwf PCLATH ; set PCLATH movfw ta ; restore W addwf PCL ; computed GOTO dt .00 ;off dt .00 ;level1 (special handling) dt .01 dt .25 dt .70 dt .128 dt .255 END