;------ -------------------------------------------------------------------------------------------------------------------------------- ; ; "LOW FREQUENCY THREE PHASE SINE WAVE USING BIT-BANG PWM" ; ; ; ASSEMBLY SOURCE CODE FOR THE MICROCHIP PIC10F222 BY ANDRIES TIP ; ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; FUNCTIONAL DESCRIPTION OF THIS FIRMWARE: ;-------------------------------------------------------------------------------------------------------------------------------------- ; ; THIS FIRMWARE IS USED TO CREATE THREE SINE WAVES WITH 0, 120° AND 240° PHASE SHIFT AT 7.8 HZ FROM THREE PWM SIGNALS CREATED BY ; THE PIC. THIS CODE SPREADS THE BITS OF EACH PWM PERIOD INSTEAD OF PLACING THEM ALL AT THE START OR AT THE END OF THE PERIOD. ; THIS IS DONE TO MINIMIZE THE VOLTAGE RIPPLE AT THE OUTPUTS OF THE RC-FILTERS WHICH ARE CONNECTED TO EACH PWM OUTPUT PIN. ; EFFECTIVELY WE WILL GET A VARIABLE, STEPPING PWM FREQUENCY. ; ; EXAMPLE TRADITIONAL PWM WITH 16 BITS IN ONE PERIOD (4 HIGH, 12 LOW): ; ; 0123456789ABCDEF0123456789ABCDEF ; ; ____ ____ ; | |___________| |___________ ; ; ; EXAMPLE OF THIS BIT SPREADING PWM WITH 16 BITS IN ONE PERIOD (4 HIGH, 12 LOW): ; ; 0123456789ABCDEF0123456789ABCDEF ; ; _ _ _ _ _ _ _ _ ; ___|___|___|___|___|___|___|___| ; ; ; THE SPREADING IS ACHIEVED BY SIMPLY ADDING THE DUTY CYCLE (0.25 IN THE EXAMPLE) TO A VARIABLE AT THE START OF EVERY BIT TIME. ; EVERY TIME THE VARIABLE REACHES 1 ("ROLLS OVER"), A VALUE OF ONE WILL BE SUBTRACTED FROM THE VARIABLE AND THE OUTPUT WILL BE ; MADE HIGH. THIS VARIABLE WILL BE INITIALIZED TO ZERO WHENEVER THE PIC IS RESET. ; ; HERE YOU CAN SEE THE VALUE OF THE VARIABLE CHANGE OVER TIME: ; ; BIT VALUE OUTPUT ; ; 0 0.25 LOW ; 1 0.50 LOW ; 2 0.75 LOW ; 3 1.00 HIGH ; 4 0.25 LOW ; 5 0.50 LOW ; 6 0.75 LOW ; 7 1.00 HIGH ; 8 0.25 LOW ; 9 0.50 LOW ; A 0.75 LOW ; B 1.00 HIGH ; C 0.25 LOW ; D 0.50 LOW ; E 0.75 LOW ; F 1.00 HIGH ; . ; . ; . ; ; ; IN THIS FIRMWARE FOR A THREE PHASE SINE WE USE SINE TABLE VALUES FROM 0 TO 255 FOR 0% TO 100% DUTY CYCLE. THEREFORE WE SHOULD ; ACTUALLY TEST FOR 255 AS ROLLOVER VALUE ("1" AS DESCRIBED ABOVE), BUT IT IS FASTER TO TEST FOR 256 (CARRY BIT!). FOR THIS ; PARTICULAR APPLICATION IN WHICH THESE THREE SINE WAVES ARE USED WE CAN ACCEPT THIS SMALL DISCREPANCY (99.6% INSTEAD OF 100%) ; WE USE "RLF" INSTRUCTIONS TO SHIFT THE CARRY BITS (ONE FOR EACH PHASE) INTO PLACE, READY TO BE COPIED TO THE OUTPUT PORT. ; THIS IS POSSIBLE SINCE WE DON'T USE ANY OTHER OUTPUT PINS (ON THIS PORT). HERE WE USE A 360° SINE WAVE TABLE. WE COULD DO WITH A ; 90° TABLE, BUT THEN THE REST OF THE CODE WOULD BE MORE COMPLICATED. ; ; FOR MAXIMUM PRECISION (100%) WE WILL GET MORE RIPPLE BECAUSE THE PWM BITS WILL TAKE MORE INSTRUCTION CYCLES, PLEASE SEE BELOW: ; ; . ; . ; MOVF WTA,W ; UPDATE OUT1,A ; ADDWF PHASEA,F ; ; RLF OUT1,F ; ; . ; . ; ; WILL BECOME: ; . ; . ; COMF WTA,W ; UPDATE OUT1,A ; SUBWF PHASEA,F ; ; SKPC ; ; DECF PHASEA,F ; ; RLF OUT1,F ; ; . ; . ; ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; PINOUT ;-------------------------------------------------------------------------------------------------------------------------------------- ; ; PORT GP0/AN0/ICSPDAT = DIGITAL OUTPUT PWM OUTPUT PHASE1 ; PORT GP1/AN1/ICSPCLK = DIGITAL OUTPUT PWM OUTPUT PHASE2 ; PORT GP2/T0CLK/FOSC4 = DIGITAL OUTPUT PWM OUTPUT PHASE3 ; PORT GP3/NOT_MCLR/VPP = DIGITAL INPUT NOT USED (WITH INTERNAL PULL-UP TO PREVENT TOGGLING INPUT) ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; CONFIGURATION ;-------------------------------------------------------------------------------------------------------------------------------------- INCLUDE P10F222.INC __CONFIG _MCLRE_OFF & _CP_ON & _WDT_OFF & _MCPU_OFF & _IOSCFS_8MHZ ; 8 MHZ INTERNAL CLOCK => 2 MHZ INSTRUCTION CLOCK => ONE INSTRUCTION TAKES 0.5 MICROSECOND ;-------------------------------------------------------------------------------------------------------------------------------------- ; VARIABLE DEFINITIONS ;------------------------------------------------------------------------------------------------------------------------------------- CBLOCK 0X09 PHASEA ; SINE WAVE DUTY CYCLE DATA (0..255, CORRESPONDING TO 0%..100% DUTY CYCLE) PHASEB ; PHASEC ; POINTER ; POINTER TO DUTY CYCLE VALUE IN WAVE TABLE (MAXIMUM ADDRESS RANGE = 1..253) LOOPCOUNT ; OBVIOUS NEWA ; NEW WAVE TABLE VALUES NEWB ; NEWC ; WTA ; WAVE TABLE VALUES WTB ; WTC ; OUT1 ; TEMPORARY STORAGE FOR OUTPUT VALUES OUT2 ; ENDC ;-------------------------------------------------------------------------------------------------------------------------------------- ; START OF MAIN PROGRAM ;-------------------------------------------------------------------------------------------------------------------------------------- ORG H'000' ; TELL THE ASSEMBLER TO PLACE FOLLOWING PROGRAM CODE AT BOTTOM OF THE PROGRAM MEMORY. START ; IN CONTRAST TO THE 14- AND 16- BIT PICS, THE 12-BIT-PICS (LIKE THIS ONE) DO NOT START ; INSTRUCTION EXECUTION AT H'000' (FOR EXAMPLE AT POWER-ON), BUT AT THE VERY LAST FLASH-MEMORY ; ADDRESS. AT THAT LOCATION THERE IS A 'MOVLW K' INSTRUCTION WHICH HOLDS THE CALIBRATION VALUE ; FOR THE INSTRUCTION CLOCK FOR EACH INDIVIDUAL PIC. THIS VALUE HAS BEEN STORED AT THE FACTORY ; AND SHOULD NOT BE OVERWRITTEN OR THE CALIBRATION WILL BE LOST AND PROGRAM EXECUTION TIMING ; IS AFFECTED. AFTER EXECUTING THE 'MOVLW K' INSTRUCTION THE PIC WILL JUMP TO ADDRESS H'000' ; AND PROGRAM EXECUTION MAY BEGIN. THE FIRST INSTRUCTION OF EACH PROGRAM SHOULD USE THE W ; REGISTER VALUE TO CALIBRATE THE INSTRUCTION CLOCK. GOTO INITIALIZE ; ALL CODE IS PLACED IN HIGH MEMORY BECAUSE WE NEED ALL OF THE LOW MEMORY FOR THE SINE TABLE ;-------------------------------------------------------------------------------------------------------------------------------------- RETLW D'0' ; 360° SINE WAVE TABLE RETLW D'0' RETLW D'0' RETLW D'0' RETLW D'1' RETLW D'1' RETLW D'2' RETLW D'2' RETLW D'3' RETLW D'4' RETLW D'5' RETLW D'6' RETLW D'7' RETLW D'8' RETLW D'9' RETLW D'10' RETLW D'12' RETLW D'13' RETLW D'15' RETLW D'17' RETLW D'18' RETLW D'20' RETLW D'22' RETLW D'24' RETLW D'26' RETLW D'28' RETLW D'31' RETLW D'33' RETLW D'35' RETLW D'38' RETLW D'40' RETLW D'43' RETLW D'45' RETLW D'48' RETLW D'51' RETLW D'54' RETLW D'56' RETLW D'59' RETLW D'62' RETLW D'65' RETLW D'68' RETLW D'71' RETLW D'75' RETLW D'78' RETLW D'81' RETLW D'84' RETLW D'87' RETLW D'91' RETLW D'94' RETLW D'97' RETLW D'101' RETLW D'104' RETLW D'108' RETLW D'111' RETLW D'115' RETLW D'118' RETLW D'121' RETLW D'125' RETLW D'128' RETLW D'132' RETLW D'135' RETLW D'139' RETLW D'142' RETLW D'146' RETLW D'149' RETLW D'152' RETLW D'156' RETLW D'159' RETLW D'163' RETLW D'166' RETLW D'169' RETLW D'172' RETLW D'176' RETLW D'179' RETLW D'182' RETLW D'185' RETLW D'188' RETLW D'191' RETLW D'194' RETLW D'197' RETLW D'200' RETLW D'203' RETLW D'206' RETLW D'208' RETLW D'211' RETLW D'214' RETLW D'216' RETLW D'219' RETLW D'221' RETLW D'223' RETLW D'226' RETLW D'228' RETLW D'230' RETLW D'232' RETLW D'234' RETLW D'236' RETLW D'237' RETLW D'239' RETLW D'241' RETLW D'242' RETLW D'244' RETLW D'245' RETLW D'247' RETLW D'248' RETLW D'249' RETLW D'250' RETLW D'251' RETLW D'252' RETLW D'252' RETLW D'253' RETLW D'254' RETLW D'254' RETLW D'254' RETLW D'255' RETLW D'255' RETLW D'255' RETLW D'255' RETLW D'255' RETLW D'255' RETLW D'254' RETLW D'254' RETLW D'254' RETLW D'253' RETLW D'252' RETLW D'252' RETLW D'251' RETLW D'250' RETLW D'249' RETLW D'248' RETLW D'247' RETLW D'245' RETLW D'244' RETLW D'242' RETLW D'241' RETLW D'239' RETLW D'237' RETLW D'236' RETLW D'234' RETLW D'232' RETLW D'230' RETLW D'228' RETLW D'226' RETLW D'223' RETLW D'221' RETLW D'219' RETLW D'216' RETLW D'214' RETLW D'211' RETLW D'208' RETLW D'206' RETLW D'203' RETLW D'200' RETLW D'197' RETLW D'194' RETLW D'191' RETLW D'188' RETLW D'185' RETLW D'182' RETLW D'179' RETLW D'176' RETLW D'172' RETLW D'169' RETLW D'166' RETLW D'163' RETLW D'159' RETLW D'156' RETLW D'152' RETLW D'149' RETLW D'146' RETLW D'142' RETLW D'139' RETLW D'135' RETLW D'132' RETLW D'128' RETLW D'125' RETLW D'121' RETLW D'118' RETLW D'115' RETLW D'111' RETLW D'108' RETLW D'104' RETLW D'101' RETLW D'97' RETLW D'94' RETLW D'91' RETLW D'87' RETLW D'84' RETLW D'81' RETLW D'78' RETLW D'75' RETLW D'71' RETLW D'68' RETLW D'65' RETLW D'62' RETLW D'59' RETLW D'56' RETLW D'54' RETLW D'51' RETLW D'48' RETLW D'45' RETLW D'43' RETLW D'40' RETLW D'38' RETLW D'35' RETLW D'33' RETLW D'31' RETLW D'28' RETLW D'26' RETLW D'24' RETLW D'22' RETLW D'20' RETLW D'18' RETLW D'17' RETLW D'15' RETLW D'13' RETLW D'12' RETLW D'10' RETLW D'9' RETLW D'8' RETLW D'7' RETLW D'6' RETLW D'5' RETLW D'4' RETLW D'3' RETLW D'2' RETLW D'2' RETLW D'1' RETLW D'1' RETLW D'0' RETLW D'0' RETLW D'0' RETLW D'0' ;-------------------------------------------------------------------------------------------------------------------------------------- JUMP_GETVALUE ORG H'0FE' ; MOVF POINTER,W ; LET W POINT TO ADDRESS OF THE VALUE MOVWF PCL ; JUMP TO CALCULATION ; NOTE: FOR THIS 12-BIT PROCESSOR WE CAN ONLY JUMP THIS WAY IN THE LOWER 256 MEMORY LOCATIONS, ; BECAUSE THE 8TH BIT WILL ALWAYS BE RESET TO ZERO (THE 10F222 HAS 512 MEMORY LOCATIONS !) ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- INITIALIZE ORG H'100' ; FIRST INSTRUCTION OF SECOND MEMORY HALF (PIC10F222) INIT_OSCCAL ANDLW B'11111110' ; FACTORY OSCCAL VALUE ALREADY IN W, WE DO NOT WANT OSCILLATOR OUTPUT AT GP2: CLEAR BIT 0 MOVWF OSCCAL ; THE OSCILLATOR CALIBRATION VALUE IS STORED AT THE LAST MEMORY ADDRESS INIT_GPIO CLRF GPIO ; VALUE FOR ALL OUTPUTS (GP0, GP1 AND GP2) LOW MOVLW B'11111000' ; MAKE GP0, GP1 AND GP2 OUTPUTS, MAKE GP3 (UNUSED) INPUT TRIS GPIO ; INIT_AD CLRF ADCON0 ; WE DO NOT USE THE ANALOG-DIGITAL CONVERTER: GP0 AND GP1 DIGITAL, SELECT AN0, NO CONV, ADC OFF INITALIZE CLRWDT ; WE NEED TO CLEAR THE WATCHDOG TIMER FIRST OR ELSE WE MAY GET A RESET, ALSO CLEARS PRESCALER CLRF TMR0 ; CLEAR TIMER0 AND THE PRESCALER MOVLW B'10001100' ; VALUE FOR NO WAKE-UP ON PIN CHANGE, GPIO PULL-UPS, TMR0 FROM INSTRUCTION CLOCK 1:1, ASSIGN OPTION ; THE PRESCALER TO THE WATCHDOG 1:16 (16 * 18 MS = 0.288 SECOND WATCHDOG TIMEOUT = 3.47 HZ) ;--------------- ---------------------------------------------------------------------------------------------- INIT_VARIABLES CLRF PHASEA ; CLRF PHASEB ; CLRF PHASEC ; CLRF WTA ; WAVE TABLE VALUES CLRF WTB ; CLRF WTC ; CLRF NEWA ; NEW WAVE TABLE VALUES CLRF NEWB ; CLRF NEWC ; CLRF OUT1 ; START WITH ALL OUTPUTS LOW CLRF OUT2 ; MOVLW D'1' ; SELECT FIRST VALUE IN SINE WAVE TABLE MOVWF POINTER ; MOVWF LOOPCOUNT ; FOR FAST STARTUP ;--------------- ---------------------------------------------------------------------------------------------- MAINLOOP ; CALCULATION OF THE VALUES TO ACHIEVE THE DESIRED SINE WAVE: ; FOSC = 8 MHZ ; FINSTR = FOSC/4 = 2 MHZ ; FSINE = 7.80 HZ ; THEREFORE THE NUMBER OF INSTRUCTIONS FOR ONE COMPLETE SINE WAVE = 2000000 / 7.80 = 256410 ; IN THIS 12-BIT PIC WE CAN ONLY USE THE LOWER 256 PROGRAM MEMORY PLACES FOR THE WAVE TABLE ; BECAUSE OF THE LIMITATION IN THE JUMP RANGE (BIT8 OF DESTINATION ADDRESS WILL ALWAYS BE ZERO) ; THE FIRST INSTRUCTION NEEDS TO BE A GOTO TO THE PROGRAM CODE FURTHER UP IN THE PROGRAM MEMORY ; THE LAST TWO INSTRUCTION IN THE LOW PART OF THE PROGRAM MEMORY ARE NEEDED TO PERFORM THE JUMP ; THEREFORE THE MAXIMUM NUMBER OF ENTRIES IN THE WAVE TABLE = 256 - 3 = 253 ; FOR NOW, AND TO KEEP THE PROGRAM CODE AS SHORT AS POSSIBLE, THE WAVE TABLE WILL HOLD ONE ; COMPLETE SINE WAVE EVEN THOUGH A QUARTER OF A SINE WAVE WOULD SUFFICE FOR RECONSTRUCTION OF ; A COMPLETE SINE WAVE ; BECAUSE WE NEED THREE DIFFERENT OUTPUT PHASES, EACH SHIFTED 120°, WE WILL DIVIDE THIS NUMBER ; BY THREE TO SEE WHEN WE WILL HAVE AN INTEGER NUMBER BETWEEN THE PHASES: ; 253/3 = 84.333 WHICH IS NOT AN INTEGER, THIS MEANS THE PHASES WILL NOT BE EXACTLY 120° APART ; TRY AGAIN WITH A SMALLER NUMBER FOR THE TABLE ENTRIES UNTIL WE GET AN INTEGER....WE FIND ; 252,249,246,243,240,2237,234,231,228,... ; CALCULATE THE NUMBER OF PWM BITS (TIME ELEMENTS) WE WILL HAVE FOR EACH OF THESE VALUES: ; 256410/252 = 1017.5 ; 256410/249 = 1029.759036 ; 256410/246 = 1042.317073 ; 256410/243 = 1055.185185 ; 256410/240 = 1068.375 ; 256410/237 = 1081.898734 ; 256410/234 = 1095.769231 ; 256410/231 = 1110 <<<<< THIS IS AN INTEGER, WE WILL HAVE BEST ACCURACY ! ; WE WILL TRY TO USE 231 TABLE ENTRIES (1110 INSTRUCTION CYCLES) ; ONE PWM BIT (TIME ELEMENT) TAKES 15 INSTRUCTION CYCLES, DO WE GET AN INTEGER FROM 1110/15 ? ; 1110/15 = 74 ....YES, THIS FORTUNATE COINCIDENCE ! ; - WE WILL HAVE 231 TABLE ENTRIES ; - EACH ENTRY IS USED FOR A TOTAL OF 1110 INSTRUCTION CYCLES OR 74 PWM BITS (TIME ELEMENTS) ; - THE OFFSET BETWEEN TWO PHASES IN THE WAVE TABLE IS 77 ;--------------- ---------------------------------------------------------------------------------------------- BIT1_3_5_7___ ; BIT1 CODE IS 3 INSTRUCTION CYCLES SHORTER TO COMPENSATE FOR THE DELAY BY A "GOTO" INSTRUCTION GOTO $+1 ; 2 INSTRUCTION CYCLE DELAY MOVF NEWA,W ; USE THE NEW WAVETABLE VALUE TO UPDATE OUT1,A: ADDWF PHASEA,F ; CALCULATE IF IT IS TIME TO MAKE THE OUTPUT HIGH, CARRY SET IF YES RLF OUT1,F ; SHIFT THE CARRY BIT INTO PLACE MOVF NEWB,W ; USE THE NEW WAVETABLE VALUE TO UPDATE OUT1,B: ADDWF PHASEB,F ; CALCULATE IF IT IS TIME TO MAKE THE OUTPUT HIGH, CARRY SET IF YES RLF OUT1,F ; SHIFT THE CARRY BIT INTO PLACE MOVF NEWC,W ; USE THE NEW WAVETABLE VALUE TO UPDATE OUT1,C: ADDWF PHASEC,F ; CALCULATE IF IT IS TIME TO MAKE THE OUTPUT HIGH, CARRY SET IF YES RLF OUT1,W ; SHIFT THE CARRY BIT INTO PLACE AND PUT RESULT IN W ! MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT2_4_6_8___ MOVF NEWB,W ; COPY THE NEW VALUES FOR A, B AND C MOVWF WTB ; MOVF NEWC,W ; MOVWF WTC ; MOVF NEWA,W ; A IS COPIED LAST BECAUSE WE WILL USE W FOR THE ADDITION TOO, UPDATE OUT1,A MOVWF WTA ; ADDWF PHASEA,F ; RLF OUT1,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT63 DECFSZ LOOPCOUNT,F ; HAVE WE DONE ALL BITS 1..62 ? GOTO BIT1_3_5_7___ ; NO, GO DO ANOTHER TWO BITS NOP ; 1 INSTRUCTION CYCLE DELAY MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; ADDWF PHASEA,F ; UPDATE OUT2,A ! RLF OUT2,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT64 CALL JUMP_GETVALUE ; FETCH NEW A VALUE FROM SINE WAVE TABLE (THIS LINE TAKES 7 INSTRUCTION CYCLES) USING POINTER MOVWF NEWA ; MOVF WTB,W ; UPDATE OUT2,B ! ADDWF PHASEB,F ; RLF OUT2,F ; MOVF WTC,W ; UPDATE OUT2,C ! ADDWF PHASEC,F ; RLF OUT2,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT65 MOVLW D'77' ; 120° PHASE SHIFT WHEN TABLE LENGTH FOR ONE COMPLETE SINE HAS 231 ENTRIES (231/3 = 77) ADDWF POINTER,F ; ADJUST POINTER VALUE FOR B MOVLW D'231' ; PREPARE TO ADJUST THE POINTER AFTER OVERFLOW SKPNC ; IS THE POINTER NOW 256 OR MORE ? SUBWF POINTER,F ; YES, CORRECT POINTER VALUE MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT66 MOVLW D'232' ; STAY WITHIN TABLE SUBWF POINTER,W ; MOVLW D'231' ; SKPNC ; IS THE POINTER NOW 232 OR MORE ? SUBWF POINTER,F ; YES, CORRECT POINTER VALUE MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT67 GOTO $+1 ; 3 INSTRUCTION CYCLE DELAY NOP ; MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; ADDWF PHASEA,F ; UPDATE OUT2,A ! RLF OUT2,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT68 CALL JUMP_GETVALUE ; FETCH NEW B VALUE FROM SINE WAVE TABLE (THIS LINE TAKES 7 INSTRUCTION CYCLES) USING POINTER MOVWF NEWB ; MOVF WTB,W ; UPDATE OUT2,B ! ADDWF PHASEB,F ; RLF OUT2,F ; MOVF WTC,W ; UPDATE OUT2,C ! ADDWF PHASEC,F ; RLF OUT2,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT69 MOVLW D'77' ; 120° PHASE SHIFT WHEN TABLE LENGTH FOR ONE COMPLETE SINE HAS 231 ENTRIES (231/3 = 77) ADDWF POINTER,F ; ADJUST POINTER VALUE FOR C MOVLW D'231' ; PREPARE TO ADJUST THE POINTER AFTER OVERFLOW SKPNC ; IS THE POINTER NOW 256 OR MORE ? SUBWF POINTER,F ; YES, CORRECT POINTER VALUE MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT70 MOVLW D'232' ; STAY WITHIN TABLE SUBWF POINTER,W ; MOVLW D'231' ; SKPNC ; IS THE POINTER NOW 232 OR MORE ? SUBWF POINTER,F ; YES, CORRECT POINTER VALUE MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT71 MOVLW D'31' ; PREPARE THE LOOP MOVWF LOOPCOUNT ; NOP ; 1 INSTRUCTION CYCLE DELAY MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; ADDWF PHASEA,F ; UPDATE OUT2,A ! RLF OUT2,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT72 CALL JUMP_GETVALUE ; FETCH NEW C VALUE FROM SINE WAVE TABLE (THIS LINE TAKES 7 INSTRUCTION CYCLES) USING POINTER MOVWF NEWC ; MOVF WTB,W ; UPDATE OUT2,B ! ADDWF PHASEB,F ; RLF OUT2,F ; MOVF WTC,W ; UPDATE OUT2,C ! ADDWF PHASEC,F ; RLF OUT2,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT73 MOVLW D'77' ; 120° PHASE SHIFT WHEN TABLE LENGTH FOR ONE COMPLETE SINE HAS 231 ENTRIES (231/3 = 77) ADDWF POINTER,F ; ADJUST POINTER VALUE FOR A MOVLW D'231' ; PREPARE TO ADJUST THE POINTER AFTER OVERFLOW SKPNC ; IS THE POINTER NOW 256 OR MORE ? SUBWF POINTER,F ; YES, CORRECT POINTER VALUE MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- BIT74 MOVLW D'232' ; STAY WITHIN TABLE SUBWF POINTER,W ; MOVLW D'231' ; SKPNC ; IS THE POINTER NOW 232 OR MORE ? SUBWF POINTER,F ; YES, CORRECT POINTER VALUE MOVF WTA,W ; UPDATE OUT1,A ADDWF PHASEA,F ; RLF OUT1,F ; MOVF WTB,W ; UPDATE OUT1,B ADDWF PHASEB,F ; RLF OUT1,F ; MOVF WTC,W ; UPDATE OUT1,C ADDWF PHASEC,F ; RLF OUT1,W ; MOVWF GPIO ; UPDATE PORT PINS ;--------------- ---------------------------------------------------------------------------------------------- INCF POINTER,F ; NEXT POINT IN TABLE GOTO BIT1_3_5_7___ ; GO DO ANOTHER 74 BITS ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- PIC_RESET ORG H'1FF' ; THE PROCESSOR RESET VECTOR, CODE EXECUTION STARTS HERE AFTER A RESET ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- END ; TELL THE ASSEMBLER TO STOP