;************************************************************************ ; * ; Filename: dmx_basc.asm * ; Date: 21/11/02 * ; File Version: Version 2.1 * ; * ; Author: Paul Harris * ;************************************************************************ ; * ; Notes: This programme will take 4 analogue inputs * ; and DMX data inputs * ; And use them it to phase control mains * ; If Basic =1 For Model with two Leds * ; If basic =0 For Model with 7 Seg Display * ;************************************************************************ variable basic=0 ; If Basic =1 then basic version errorlevel 0, -302 RADIX DEC list p=16f870 ; list directive to define processor #include <p16f870.inc> ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _DEBUG_OFF & _CPD_OFF ; Programme constants Start_Vector EQU .0 Interrupt_Vector EQU .4 Common_Ram_Base EQU H'70' Ram_Base EQU H'20' Osc_Freq EQU .20000000 ; Pic Frequency Instruction_rate EQU Osc_Freq/.4 ; Instruction Rate ; Phase control constants Resolution EQU .256 ; Analogue dimming resolution Mains_freq EQU .100 ; 100 Parts a second Interupts_s EQU Mains_freq*Resolution ; Interupts per second Amount_to_cnt EQU Instruction_rate/Interupts_s ; number to count in timer0 Timer0_cnt EQU .256-Amount_to_cnt ; invert value to count (timer0 counts till overflow) Delay_Value EQU .40 ; DMX Constants Baud_Rate EQU .250000 Baud_Rate_Constant EQU (Osc_Freq/(.16*Baud_Rate))-.1 Number_Of_Channels EQU .6 startcode EQU .0 ; Preset Constants Max_Preset EQU .9 ; Maxium Presets allowed (EEdata = max * 4 bytes) ; *********** Define Flags ************* ; IFlag Break_Detected equ 0 ; Break detected Start_Detected equ 1 ; Start Byte detected Valid_Channel equ 2 ; Reached valid channels No_DMX_Data equ 7 ; No recieved DMX Data ; Flag longcount equ 0 ; Long count flag (2.5s) when activated presetmode equ 1 ; Preset Mode on no DMX data curve equ 2 ; S Curve selected switch equ 3 ; Switch curve selected DMX_Data equ 4 ; New DMX Data recieved phase_done equ 5 ; Flag to show mains phase complete dmx_error equ 6 ; Error detected in DMX tranmission mains_fail equ 7 ; Maind Failure Flag ; Flag2 savepreset equ 0 ; save preset started flag ; DFlag dmx_recieve equ 0 ; Dmx recieve display dmx_msb equ 1 ; Displaying DMX MSB dmx_csb equ 2 ; Displaying DMX CSB dmx_lsb equ 3 ; Displaying DMX LSB preset_intro equ 4 ; Displaying Preset Intro ; control ports #DEFINE Zerocross PORTB,0 #DEFINE channel1op PORTB,1 #DEFINE channel2op PORTB,2 #DEFINE channel3op PORTB,3 #DEFINE channel4op PORTB,4 #DEFINE Data_Rec_LED PORTC,4 ; Not Used on 7 seg Pack *** #DEFINE Data_Error_LED PORTC,5 ; Not Used on 7 seg Pack *** #DEFINE display_clk PORTC,5 ; Not Used on Basic Version #DEFINE display_data PORTC,4 ; Not Used on basic Version ;***** VARIABLE DEFINITIONS CBLOCK Common_Ram_Base Int_W Int_Status Int_PCLath Int_FSR ee_address ee_data ENDC CBLOCK Ram_Base ; Interupt Variables Iflag IH_Channel_Count_L IH_Channel_Count_H IH_Channels_Recieved IH_Temp IH_Long_Count ; Long duration count (2.5s) IH_Timer_Count IH_position_count IH_channel1cnt ; intertupt counts IH_channel2cnt IH_channel3cnt IH_channel4cnt ; Programme variables countervalue ; Preset to load timer 1 from position_count ; Number of positions in last mains pulse Current_Preset ; Current Preset being displayed flag ; general flags flag2 ; General flag dflag ; Display Flags Delay_Count ; Counter used in delay routien display_count ; Used for 7 Seg display displayvalue ; Used for 7 Seg display olddisplayvalue shadowa ; Port A shadow register oldporta ; Old Port a Value process_temp ; Process Tempory value tbllo ; Table Low Value NumH ; BIN -> BCD NumL ; BIN -> BCD Hund ; BIN -> BCD Tens_Ones ; BIN -> BCD dmx_hund ; BCD Value dmx_ten ; BCD Value dmx_one ; BCD Value DMX_Start_Addr_L ; DMX Start Address DMX_Start_Addr_H DMX_Start_Code ; DMX Start Code Channels ; Number of channels channel1update ; Update values for interupt count channel2update channel3update channel4update Channel_Values : (Number_Of_Channels+2) ENDC ;********************************************************************** ORG Start_Vector ; processor reset vector nop ; Included for ICD clrf PCLATH ; ensure page bits are cleared goto Start ; go to beginning of program ORG Interrupt_Vector ; interrupt vector location MOVWF Int_W ; Save PIC state SWAPF STATUS,W CLRF STATUS MOVWF Int_Status MOVF PCLATH,W MOVWF Int_PCLath CLRF PCLATH BCF STATUS,IRP MOVF FSR,W MOVWF Int_FSR IH_Interrupt_Poll btfsc INTCON,T0IF ; Test for timer0 interupt goto IH_Timer0 ; Yes, Goto timer0 Handler btfsc PIR1,RCIF ; USART Interupt Pending ? goto IH_Check_USART ; Yes, Goto Usart handler btfsc INTCON,INTF ; Test for RB0 Interupt goto IH_RB0 btfsc PIR1,TMR1IF ; Timer 1 interupt ?? goto IH_Timer1 IH_Exit movf Int_FSR,W ; Restore PIC state movwf FSR movf Int_PCLath,W movwf PCLATH swapf Int_Status,W movwf STATUS swapf Int_W,F swapf Int_W,W retfie ; Return from interrupt IH_Timer0 movf countervalue,w movwf TMR0 ; Reload counter0 ; Channel 1 decf IH_channel1cnt,f; decrease channel 1 count btfsc STATUS,Z ; if zero then set output bcf channel1op ; set output ; Channel 2 decf IH_channel2cnt,f; decrease channel 2 count btfsc STATUS,Z ; if zero then set output bcf channel2op ; set output ; Channel 3 decf IH_channel3cnt,f; decrease channel 3 count btfsc STATUS,Z ; if zero then set output bcf channel3op ; set output ; Channel 4 decf IH_channel4cnt,f; decrease channel 4 count btfsc STATUS,Z ; if zero then set output bcf channel4op ; set output incf IH_position_count,f ; increse pulse count bcf INTCON,T0IF ; Clear interupt goto IH_Interrupt_Poll IH_RB0 bsf STATUS,RP0 ; change to bank 1 btfsc OPTION_REG,INTEDG ; Test which edge of zerocross looking for goto IH_RB0_End ; 1 = rising edge IH_RB0_Start bsf OPTION_REG,INTEDG ; set to look for Rising Edge bcf OPTION_REG,T0CS ; Enable timer 0 bcf STATUS,RP0 ; move back to bank 0 bcf INTCON,INTF ; Clear interupt flag clrf IH_position_count ; clear pulse count bsf INTCON,T0IF ; Create timer Interupt clrf TMR1L ; Clear Timer1 clrf TMR1H bcf flag,mains_fail ; and flags.... btfsc PIR1,RCIF ; Is USART interrupt Pending ? goto IH_Check_USART ; Yes, Do USART rec bit before going to handler. incfsz IH_Timer_Count,f ; No, Increase No DMX Data Count goto IH_Interrupt_Poll ; If NOT Zero then goto handler if basic == 1 bcf Data_Rec_LED ; If Zero, Clear DMX data recieve LED bcf Data_Error_LED ; And the DMX Error LED endif bcf flag,DMX_Data ; Clear DMX recieve flag clrf Iflag ; Clear any DMX data being recieved goto IH_Interrupt_Poll IH_RB0_End bsf OPTION_REG,T0CS ; Disable Timer 0 bcf INTCON,INTF ; Clear Interupt flag bcf OPTION_REG,INTEDG ; Set RB0 Interupt to falling edge bcf STATUS,RP0 ; change to bank 0 movlw .254 movwf PORTB ; clear ouputs movf channel1update,w ; reload channel count movwf IH_channel1cnt movf channel2update,w ; reload channel count movwf IH_channel2cnt movf channel3update,w ; reload channel count movwf IH_channel3cnt movf channel4update,w ; reload channel count movwf IH_channel4cnt movf IH_position_count,w ; save pulse count movwf position_count bsf flag,phase_done decfsz IH_Long_Count,f ; Decrease Long Count goto IH_Interrupt_Poll bsf flag,longcount ; set long count goto IH_Interrupt_Poll IH_Check_USART bcf PIR1,RCIF ; Clear Interupt flag ;bsf Data_Rec_LED ; Set DMX Data LED IH_Check_HW_Overrun btfsc RCSTA,OERR ; Has a HW overrun occurred ? goto IH_HW_Overrun ; Yes, do a HW reset IH_Check_9th_bit clrf IH_Timer_Count ; Clear Timer count btfss RCSTA,RX9D ; Dose 9th Bit of data = 1, eg Break goto IH_Wait_Break ; Yes, start receiving again IH_Check_SW_Overrun btfsc RCSTA,FERR ; Has a framing error occurred ? goto IH_SW_Overrun ; Yes, do a Usart reset IH_Test_Flags btfsc Iflag,Valid_Channel ; Test to see if receiving valid channels goto IH_Valid_Channel ; Yes, get next channel btfsc Iflag,Start_Detected ; Test to see it start byte has arrived goto IH_Wait_Channel ; Yes, Check Channel counts btfsc Iflag,Break_Detected ; Test to see if break has arrived goto IH_Wait_Start ; Yes, wait for start byte IH_Wait_Break clrf Iflag ; Clear all interupt flags movf RCREG,w ; Move recieved data in to w btfsc RCSTA,RX9D ; Test if break has arrived goto IH_Interrupt_Poll ; No, Break not detected btfsc STATUS,Z ; Yes, Dose detected break =0 ? bsf Iflag,Break_Detected ; Yes, set flag to indicate break arrived goto IH_Interrupt_Poll IH_Wait_Start clrf IH_Channels_Recieved ; Clear number of channels recieved clrf IH_Channel_Count_L ; Clear Low channel count clrf IH_Channel_Count_H ; Clear High channel count bsf Iflag,Start_Detected ; Set flag to indicate Start Byte arrived movf RCREG,w ; Check start code = 0 btfss STATUS,Z ; clrf Iflag ; if No then clear flags and wait for next break goto IH_Interrupt_Poll IH_Wait_Channel movf RCREG,w ; Store Recieved value in temp movwf IH_Temp incf IH_Channel_Count_L,f ; Increase channel count btfsc STATUS,Z ; for both Low and High bytes incf IH_Channel_Count_H,f ; movf IH_Channel_Count_H,w ; Compare the high byte of channel count to xorwf DMX_Start_Addr_H,w ; DMX start address btfss STATUS,Z ; If Not equal then exit goto IH_Interrupt_Poll movf IH_Channel_Count_L,w ; Compare the low byte of channel count to xorwf DMX_Start_Addr_L,w ; DMX Start address btfss STATUS,Z ; if not equal then exit goto IH_Interrupt_Poll bsf Iflag,Valid_Channel ; if address equal then set valid channels movf IH_Temp,w movwf Channel_Values ; Store value in first channel incf IH_Channels_Recieved,f ; and increase count goto IH_Interrupt_Poll IH_Valid_Channel movlw Channel_Values ; Load address of memory block addwf IH_Channels_Recieved,w ; add channel offset movwf FSR ; and move in to FSR movf RCREG,w ; Store result in the movwf INDF ; channel position in memory movf IH_Channels_Recieved,w ; incf IH_Channels_Recieved,f ; Increase count (Note No effect on w !) xorwf Channels,w ; Check if all channels recieved btfss STATUS,Z ; goto IH_Interrupt_Poll ; No, then return to interupt poll clrf Iflag ; Yes, Clear flags and wait for break if basic == 1 bsf Data_Rec_LED ; Set DMX Data LED endif bsf flag,DMX_Data ; Set DMX Data recieve flag goto IH_Interrupt_Poll ; exit back to Handler IH_HW_Overrun bcf RCSTA,CREN ; Reset UART bsf RCSTA,CREN ; receive logic bsf flag,dmx_error ; Turn on hardware overrun LED if basic == 1 bsf Data_Error_LED ; Turn on DMX Error led endif goto IH_Check_9th_bit IH_SW_Overrun bcf RCSTA,CREN ; reset UART bsf RCSTA,CREN ; receive logic bsf flag,dmx_error ; Turn on software Overrun Led if basic == 1 bsf Data_Error_LED ; Turn on DMX Error led endif goto IH_Test_Flags IH_Timer1 ; Mains Phase Fail bcf PIR1,TMR1IF ; Clear interupt flag bsf flag,mains_fail ; Set Mains Fail Flag movlw .254 movwf PORTB ; clear ouputs goto IH_Exit ; --------------------------------------------------------------------------- seg_table ; Table for 7 Segment display addwf PCL,f ; Place before possible programme retlw .129 ; 0 retlw .243 ; 1 retlw .73 ; 2 retlw .97 ; 3 retlw .51 ; 4 ; Web Site Version retlw .37 ; 5 retlw .7 ; 6 retlw .241 ; 7 retlw .1 ; 8 retlw .49 ; 9 retlw .67 ; d retlw .17 ; A retlw .25 ; P retlw .13 ; E retlw .79 ; c retlw .23 ; h retlw .255 ; <OFF> ; --------------------------------------------------------------------------- Start clrf PORTA ; \ movlw .254 ; Clear ports movwf PORTB ; clrf PORTC ; / clrf flag ; Clear flag register clrf flag2 clrf Iflag ; Clear Interupt flag clrf dflag ; Clear Display Flags clrf DMX_Start_Addr_L; Clear DMX Address clrf DMX_Start_Addr_H; clrf Current_Preset clrf olddisplayvalue clrf STATUS ; Clear status bsf STATUS,RP0 ; Set up port I/O directions movlw B'11111111' ; 1 = Input 0 = Output movwf TRISA ; Make PORTA all input movlw B'00000001' movwf TRISB ; Make PORTB all Output expect PB0 movlw B'000000000' ; Set AN0 - AN4 As analogue inputs left justified movwf ADCON1 movlw B'11001000' ; set up options - Timer0 from instruction cycle clock with movwf OPTION_REG ; no prescaler Get_DMX_Address movlw B'10001111' ; Set Up Switch directions movwf TRISC bcf STATUS,RP0 ; Go back to bank 0 nop movlw B'00010000' ; Enable first bank of switches movwf PORTC call Delay ; Go for a little delay movf PORTC,w ; Read Port C andlw B'00001111' ; Mask un required bits movwf DMX_Start_Addr_L; Store in addrees Low movlw B'00100000' ; Get next bank of switches movwf PORTC call Delay swapf PORTC,w ; Read switches and swap nibbles andlw B'11110000' ; Mask undesirables iorwf DMX_Start_Addr_L,f ; Store Higher nibble movlw B'01000000' ; Get final bank of switches movwf PORTC call Delay movf PORTC,w ; get switches andlw B'00001111' ; mask narstry bits movwf process_temp andlw B'00001110' ; store other switch settings in flags. movwf flag btfsc process_temp,0 ; look for high address bit. incf DMX_Start_Addr_H,f ; and set if required clrf PORTC ; Clear Port C movf DMX_Start_Addr_H,w movwf NumH ; Load BIN -> BCD Converter movf DMX_Start_Addr_L,w movwf NumL call bin2dec999fast ; Get BCD version of DMX Start Address if basic == 1 ; ONLY DO FOR BASIC PACK bcf Data_Rec_LED ; Turn off Data Recieve LED bcf Data_Error_LED ; Turn Off DMX Error LED endif store_Number_channels movlw Number_Of_Channels movwf Channels ; Load Number of channels to recieve and store ; Initialize UART bsf STATUS,RP0 movlw Baud_Rate_Constant movwf SPBRG bsf TXSTA,BRGH bcf TXSTA,SYNC bsf PIE1,RCIE bcf STATUS,RP0 bsf RCSTA,RX9 bsf RCSTA,CREN bsf RCSTA,SPEN movlw B'10000001' ; Switch on the ADC channel RA0 20Mhz crystal movwf ADCON0 movlw Timer0_cnt movwf countervalue ; load counter reload variable movwf TMR0 ; Load counter bsf OPTION_REG,T0CS ; Disable timer 0 movlw B'00110001' ; Setup Timer1 movwf T1CON ; 1:8 Prescale - internal osc... clrf TMR1L ; Clear Timer clrf TMR1H bsf STATUS,RP0 ; Bank 1 bsf PIE1,TMR1IE ; Enable Timer 1 Interupt bcf STATUS,RP0 ; Interrupts clrf INTCON bsf INTCON,PEIE bsf INTCON,INTE ; Enable RB0 Interupt bsf INTCON,T0IE ; Enable Timer0 Interrupts bsf INTCON,GIE ; Enable global interrupts ; ----------------------------------------------------------------- Main btfsc flag,mains_fail ; Is Mains Ok ?????? call D_Mains_Fail ; No, btfsc flag,DMX_Data ; Is DMX Data being recieved ? goto load_update_reg ; Yes, then just updata channels if basic == 0 ; ONLY DO FOR Normal PACK btfsc flag,presetmode ; Is preset mode selected ??? *** goto preset_mode ; Yes, *** endif Get_Analogue_Values ; No, get Analogue values movlw B'10000001' ; select Channel 1 in A2D movwf ADCON0 call Delay bsf ADCON0,GO ; start ADC conversion nop nop wait1 btfsc ADCON0,GO ; Loop till conversion complete goto wait1 movf ADRESH,w ; get and movwf Channel_Values ; store channel 1 nop movlw B'10001001' ; select Channel 2 in A2D movwf ADCON0 call Delay bsf ADCON0,GO ; start ADC conversion nop nop wait2 btfsc ADCON0,GO ; Loop till conversion complete goto wait2 movf ADRESH,w ; get and movwf (Channel_Values+1) ; store channel 2 nop movlw B'10010001' ; select Channel 3 in A2D movwf ADCON0 call Delay bsf ADCON0,GO ; start ADC conversion nop nop wait3 btfsc ADCON0,GO ; Loop till conversion complete goto wait3 movf ADRESH,w ; get and movwf (Channel_Values+2) ; store channel 3 nop movlw B'10011001' ; select Channel 4 in A2D movwf ADCON0 call Delay bsf ADCON0,GO ; start ADC conversion nop nop wait4 btfsc ADCON0,GO ; Loop till conversion complete goto wait4 movf ADRESH,w ; get and movwf (Channel_Values+3) ; store channel 4 load_update_reg movf Channel_Values,w ; copy and invert value from Channel 1 call process_curve ; Get value form curve movwf channel1update movf (Channel_Values+1),w; copy and invert value from Channel 2 call process_curve ; Get value from curve movwf channel2update movf (Channel_Values+2),w; copy and invert value from Channel 3 call process_curve ; Get Value from curve movwf channel3update movf (Channel_Values+3),w; copy and invert value from Channel 4 call process_curve ; Get value from curve movwf channel4update clrf PCLATH ; Clear PCLATH from scurve. btfss flag,phase_done ; is phase complete ?? goto Main ; No, call find_countervalue ; Yes, update counter value if basic == 0 ; ONLY DO FOR Normal PACK call display ; Do display *** endif goto Main ; ******************************************************* ; * Preset Mode * ; ******************************************************* preset_mode bsf STATUS,RP0 ; Move to bank 1 movlw B'00000110' ; Set port A as digital inputs. movwf ADCON1 bcf STATUS,RP0 ; return to bank 0 nop ; delay to reset porta nop movf PORTA,w ; copy port A in to shadowa movwf shadowa xorwf oldporta,w ; look for changes andwf shadowa,w ; look for rising edge only. movwf oldporta ; and store in oldporta ! btfsc oldporta,4 call channel5 btfsc oldporta,5 call channel6 movf shadowa,w movwf oldporta btfss flag2,savepreset ; if save preset active then goto load_update_reg bsf STATUS,RP0 ; move to bank 1 movlw B'00000010' ; set PORTA back to Analogue movwf ADCON1 bcf STATUS,RP0 ; return to bank 0 nop ; Delay to reset nop goto Get_Analogue_Values ; display analogue values channel5 btfsc flag2,savepreset ; Is save preset in progress goto save_to_ee ; Yes, btfsc shadowa,5 ; No, both buttons pressed ?? goto save_preset ; Yes, movf Current_Preset,w ; No, Load Current Preset in to Status register movlw Max_Preset+1 ; set up w with new value btfsc STATUS,Z ; current preset = 0 ?? movwf Current_Preset ; Yes, reload with maxium value then decf Current_Preset,f ; No, decrease current preset goto update_preset channel6 btfsc flag2,savepreset ; Is save preset in progress goto save_to_ee ; Yes, btfsc shadowa,4 ; No, Both buttons presed ? goto save_preset ; Yes, incf Current_Preset,f ; No, Increse present preset movf Current_Preset,w sublw Max_Preset ; subtract max preset from preset btfsc STATUS,C ; To Large ?? goto update_preset clrf Current_Preset update_preset movf Current_Preset,w ; Move current preset to ee_address (in all Mem) movwf ee_address rlf ee_address,f ; * 4. rlf ee_address,f call ee_read ; Get channel 1 value movwf (Channel_Values) incf ee_address,f call ee_read ; Get channel 2 value movwf (Channel_Values+1) incf ee_address,f call ee_read ; Get channel 3 Value movwf (Channel_Values+2) incf ee_address,f call ee_read ; Get channel 4 Value movwf (Channel_Values+3) return save_preset bsf flag2,savepreset ; Set save preset mode return save_to_ee btfss shadowa,4 ; Check CH5 is selected. return ; No, btfss shadowa,5 ; Check CH6 is selected return ; No, movf Current_Preset,w ; Yes, Both channels movwf ee_address ; set up EEaddress with current preset rlf ee_address,f ; * 4 rlf ee_address,f movf (Channel_Values),w movwf ee_data call ee_write ; save Channel 1 Value incf ee_address,f movf (Channel_Values+1),w movwf ee_data call ee_write ; save Channel 2 Value incf ee_address,f movf (Channel_Values+2),w movwf ee_data call ee_write ; Save Channel 3 Value incf ee_address,f movf (Channel_Values+3),w movwf ee_data call ee_write ; save Channel 4 Value bcf flag2,savepreset ; Clear flag clrf oldporta ; to prevent rerunning return ; ********************************************************* ; * Display Errors * ; * Input - flags Output - Nothing * ; ********************************************************* D_Mains_Fail if basic == 1 bsf Data_Rec_LED ; Switch On Both LEDs bsf Data_Error_LED ; else movlw .15 ; Display a F for Mains Fail call seven_seg endif bcf INTCON,T0IE ; Disable Timer0 Interrupts D_No_Mains_Loop ; No Mains Loop........ btfsc flag,mains_fail goto D_No_Mains_Loop call Delay bsf INTCON,T0IE ; Enable Timer0 Interrupts return ; *********************************************** ; * Display Routien * ; * Input - Control flags output - Nothing * ; *********************************************** display btfsc flag,DMX_Data ; Dmx Currently ?? goto dmx_display ; Yes, movlw B'11110000' ; No, Clear dmx part of dflag andwf dflag,f bcf flag,dmx_error ; clear dmx error flag btfsc flag,presetmode ; In Preset Mode Currently goto preset_display ; Yes, analogue_display ; No, movlw .11 ; Display A goto seven_seg dmx_display bcf dflag,preset_intro btfsc flag,dmx_error ; Dmx error recieved ?? goto display_error ; Yes, btfsc dflag,dmx_lsb ; Displaying LSB ?? goto display_d ; Yes, btfsc dflag,dmx_csb ; Displaying CSB ?? goto display_lsb ; Yes, btfsc dflag,dmx_msb ; Displaying MSB ?? goto display_csb ; Yes, btfsc dflag,dmx_recieve ; Displaying New d ?? goto display_msb ; Yes, clrf IH_Long_Count bcf flag,longcount ; Clear and reset Long Count bsf dflag,dmx_recieve movlw .10 ; display d. goto seven_seg display_msb btfss flag,longcount ; Has long count finished ?? return ; No, clrf IH_Long_Count ; Yes, reset long count bcf flag,longcount bsf dflag,dmx_msb ; set display flag movf dmx_hund,w ; and display goto seven_seg display_csb btfss flag,longcount ; Has long count finished ?? return ; No, clrf IH_Long_Count ; Yes, reset long count bcf flag,longcount bsf dflag,dmx_csb ; set display flag movf dmx_ten,w ; and display goto seven_seg display_lsb btfss flag,longcount ; Has long count finished ?? return ; No, clrf IH_Long_Count ; Yes, reset long count bcf flag,longcount bsf dflag,dmx_lsb ; set display flag movf dmx_one,w ; and display goto seven_seg display_d btfss flag,longcount ; Has long count finished ?? return movlw .10 ; Value for d goto seven_seg ; And display display_error movlw .13 ; Value for E goto seven_seg ; and display preset_display btfsc flag2,savepreset ; Preset Save taking Place ?? goto display_save ; Yes, btfsc dflag,preset_intro ; Done Intro Yet ?? goto display_current_preset ; Yes, display_p bsf dflag,preset_intro ; clrf IH_Long_Count ; clear and reset long count. bcf flag,longcount movlw .12 ; Value for p goto seven_seg display_current_preset btfss flag,longcount ; Wait for long count return movf Current_Preset,w ; display current preset (0 - 9) goto seven_seg display_save movlw .14 ; Save chacture = c goto seven_seg ; *********************************************** ; * 7 Segment Display Drive * ; * Input - w Output = Nothing * ; *********************************************** seven_seg movwf displayvalue xorwf olddisplayvalue,w ; Has display value changed ? btfsc STATUS,Z ; return ; No, ; Yes, Display neww value movf displayvalue,w movwf olddisplayvalue ; Update old display value call seg_table movwf displayvalue movlw .8 movwf display_count seven_loop bcf display_clk ; End of clock pulse nop btfsc displayvalue,0 ; Set next data output bsf display_data btfss displayvalue,0 bcf display_data nop nop rrf displayvalue,f ; set up next data value nop bsf display_clk ; start of clock pulse nop nop decfsz display_count,f ; all data done yet ?? goto seven_loop return ; ************************************************* ; * Find counter value required * ; * Input - position_count output - countervalue * ; ************************************************* find_countervalue ; find amount left on counter and adjust counter ; value to make counter = 255 at end. bcf flag,phase_done ; do this only after new mains cycle. btfss position_count,7; if position count >128 then decrese count goto lower_count ; else increase count higher_count movf position_count,w sublw .255 ; Sutract 254 from positioncount btfsc STATUS,C ; if < 0 then incf countervalue,f ; increase count return lower_count movf position_count,w sublw .1 ; Sutract 2 from positioncount btfss STATUS,C ; if > 0 then decf countervalue,f ; decrease count return ; ****************************************************** ; * EEREAD * ; * * ; * ee_address = Address in EEPROM w = data read * ; ****************************************************** ee_read bsf STATUS,RP1 ; Move to bank 2 movf ee_address,w movwf EEADR ; Store eeaddress in correct location bsf STATUS,RP0 ; Go to Bank 3 bcf EECON1,EEPGD ; Point to Data Memory bsf EECON1,RD ; Start EEprom read cycle bcf STATUS,RP0 ; Back to bank 2 movf EEDATA,w bcf STATUS,RP1 ; Bank to bank 0 return ; ****************************************************** ; * EEWRITE * ; * * ; * EEadr = Address in EEPROM eedata = data to write * ; ****************************************************** ee_write bcf PIR2,EEIF ; clear EE interupt flag bsf STATUS,RP1 ; Move to bank 2 bcf STATUS,RP0 ; movf ee_address,w movwf EEADR ; Save eeaddress movf ee_data,w movwf EEDATA ; save eedata bsf STATUS,RP0 ; Move to bank 3 bcf INTCON,GIE ; Disable interupts bcf EECON1,EEPGD ; Access Data Memory bsf EECON1,WREN ; put WREN movlw H'55' movwf EECON2 movlw H'AA' movwf EECON2 bsf EECON1,WR ; write cycle started bcf STATUS,RP0 ; goto Bank 0 bcf STATUS,RP1 wr1 clrwdt btfss PIR2,EEIF ; wait for EE write interupt flag goto wr1 ; write cycle wait bsf INTCON,GIE ; Enable all interupts return ; *********************************************** ; * Fast binary to decimal conversion (0..999) * ; * * ; * Input: NumH:NumL * ; * Output Hund:Tens_Ones (packed BCD) * ; * * ; * Size: 59 instructions * ; * Execution time (with return): 60 * ; * * ; * 8-July-2000 by Nikolai Golovchenko * ; * Based on 8bit BIN2BCD of Scott Dattalo * ; *********************************************** bin2dec999fast swapf NumL,w ;Add the upper and lower nibbles addwf NumL,w ;to get the one's digit andlw 0x0F skpndc ;Go through a binary to bcd addlw 0x16 ;conversion for just the one's skpndc ;digit addlw 0x06 addlw 0x06 skpdc addlw -0x06 btfsc NumL,4 ;bit 4 is a special case addlw 0x16 - 1 + 0x6 skpdc addlw -0x06 ;now adjust the ten's digit btfsc NumL,5 ;2^5 = 32, so add 3 to the ten's addlw 0x30 ;digit if bit 5 is set btfsc NumL,6 ;2^6 = 64, so add 6 addlw 0x60 ;if bit 6 is set btfsc NumL,7 ;2^7 = 128, so add 2 (the ten's addlw 0x20 ;digit) if bit 7 is set addlw 0x60 ;convert the ten's digit to bcd clrf Hund rlf Hund,f ;if there's a carry, then the input btfss Hund,0 ;was greater than 99. addlw -0x60 movwf Tens_Ones movlw 0x66 ;2^8 = 256, so add 0x56 to Tens_Ones btfsc NumH,0 movlw 0x56 + 0x66 ;add 0x66 for decimal adjust addwf Tens_Ones,f skpnc incf Hund,f clrw skpc iorlw 0x60 skpdc iorlw 0x06 subwf Tens_Ones,f movlw 0x66 ;2^9 = 512, so add 0x12 to Tens_Ones btfsc NumH,1 movlw 0x12 + 0x66 addwf Tens_Ones,f skpnc incf Hund,f clrw skpc iorlw 0x60 skpdc iorlw 0x06 subwf Tens_Ones,f btfsc NumL,7 ;finish with hundreds incf Hund,f movlw 2 btfsc NumH,0 addwf Hund,f movlw 5 btfsc NumH,1 addwf Hund,f split movf Hund,w movwf dmx_hund movf Tens_Ones,w andlw 0Fh movwf dmx_one swapf Tens_Ones,w andlw 0Fh movwf dmx_ten return ; ******************************************************* ; * Delay Loop * ; * No Input No Output * ; ******************************************************* Delay movlw Delay_Value movwf Delay_Count Delay_Loop decfsz Delay_Count,f goto Delay_Loop return ; ******************************************************* ; * Process Required Curve * ; * Input - w controls in flag output in w * ; * Inverts input to output ; ******************************************************* process_curve movwf process_temp ; Save value in w btfsc flag,switch ; Switching required ?? goto process_switching ; yes, btfsc flag,curve ; Cuve or linear ?? goto process_scurve ; Curve process_linear comf process_temp,w ; invert value in to w btfsc STATUS,Z ; If zero then movlw .1 ; make value = 1 return process_switching btfss process_temp,7 ; Look for 50 % value retlw .254 ; < 50 % ( inverted value) retlw .1 ; > 50 % ( inverted value) process_scurve ; Do table lookup. movwf tbllo ; Store low table value movlw HIGH (tablestart) ; Get High Table value movwf PCLATH ; store High Table value movlw Low (tablestart) ; add lower offset to low value addwf tbllo,w ; btfsc STATUS,C ; Carry from the addition ? incf PCLATH,f ; yes, ;movf tbllo,w ;call do_table ;clrf PCLATH ;return ;addwf PCL,f ; Do Jump movwf PCL ; Do Jump tablestart retlw .255 retlw .249 retlw .243 retlw .238 retlw .234 retlw .230 retlw .227 retlw .223 retlw .221 retlw .218 retlw .215 retlw .213 retlw .211 retlw .209 retlw .207 retlw .205 retlw .203 retlw .202 retlw .200 retlw .198 retlw .197 retlw .195 retlw .194 retlw .193 retlw .191 retlw .190 retlw .189 retlw .188 retlw .187 retlw .185 retlw .184 retlw .183 retlw .182 retlw .181 retlw .180 retlw .179 retlw .178 retlw .177 retlw .176 retlw .175 retlw .175 retlw .174 retlw .173 retlw .172 retlw .171 retlw .170 retlw .169 retlw .169 retlw .168 retlw .167 retlw .166 retlw .166 retlw .165 retlw .164 retlw .163 retlw .163 retlw .162 retlw .161 retlw .161 retlw .160 retlw .159 retlw .159 retlw .158 retlw .157 retlw .157 retlw .156 retlw .155 retlw .155 retlw .154 retlw .154 retlw .153 retlw .152 retlw .152 retlw .151 retlw .151 retlw .150 retlw .149 retlw .149 retlw .148 retlw .148 retlw .147 retlw .147 retlw .146 retlw .145 retlw .145 retlw .144 retlw .144 retlw .143 retlw .143 retlw .142 retlw .142 retlw .141 retlw .141 retlw .140 retlw .139 retlw .139 retlw .138 retlw .138 retlw .137 retlw .137 retlw .136 retlw .136 retlw .135 retlw .135 retlw .134 retlw .134 retlw .133 retlw .133 retlw .132 retlw .132 retlw .131 retlw .131 retlw .130 retlw .130 retlw .129 retlw .129 retlw .128 retlw .128 retlw .127 retlw .127 retlw .126 retlw .126 retlw .125 retlw .125 retlw .124 retlw .124 retlw .123 retlw .123 retlw .122 retlw .122 retlw .121 retlw .121 retlw .120 retlw .120 retlw .119 retlw .119 retlw .118 retlw .118 retlw .117 retlw .117 retlw .116 retlw .116 retlw .115 retlw .115 retlw .114 retlw .114 retlw .113 retlw .113 retlw .112 retlw .112 retlw .111 retlw .111 retlw .110 retlw .110 retlw .109 retlw .109 retlw .108 retlw .108 retlw .107 retlw .107 retlw .106 retlw .106 retlw .105 retlw .105 retlw .104 retlw .104 retlw .103 retlw .103 retlw .102 retlw .102 retlw .101 retlw .100 retlw .100 retlw .99 retlw .99 retlw .98 retlw .98 retlw .97 retlw .97 retlw .96 retlw .95 retlw .95 retlw .94 retlw .94 retlw .93 retlw .92 retlw .92 retlw .91 retlw .91 retlw .90 retlw .89 retlw .89 retlw .88 retlw .87 retlw .87 retlw .86 retlw .85 retlw .85 retlw .84 retlw .83 retlw .83 retlw .82 retlw .81 retlw .81 retlw .80 retlw .79 retlw .78 retlw .78 retlw .77 retlw .76 retlw .75 retlw .74 retlw .74 retlw .73 retlw .72 retlw .71 retlw .70 retlw .69 retlw .68 retlw .68 retlw .67 retlw .66 retlw .65 retlw .64 retlw .63 retlw .62 retlw .61 retlw .59 retlw .58 retlw .57 retlw .56 retlw .55 retlw .54 retlw .52 retlw .51 retlw .50 retlw .48 retlw .47 retlw .45 retlw .43 retlw .42 retlw .40 retlw .38 retlw .36 retlw .34 retlw .32 retlw .30 retlw .27 retlw .25 retlw .22 retlw .19 retlw .16 retlw .12 retlw .8 retlw .3 retlw .0 retlw .0 retlw .0 retlw .0 retlw .0 END ; directive 'end of program'