Three Phase Bit Bang by AT-planet-T9

;------
--------------------------------------------------------------------------------------------------------------------------------
;
;       "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