;-------------------------------------------------------------------------------------------------------------------------------------- ; ; ; "3 Phase Sine Wave PWM" ; ; ; Assembly source code for the Microchip PIC10F222 ; ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; ; All rights reserved - Copyright (C) 2010-2023 Sivisti / A. Tip ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; Version and history ;-------------------------------------------------------------------------------------------------------------------------------------- ; ; Start of programming : November 13, 2010 ; Last Revision Date : November 18, 2010 ; ; BE02 = added watchdog, automatic turn off when power supply voltage is low, power supply good LED ; ; BE01 = first working beta version ; __IDLOCS h'BE02' ; store the firmware version in the pic identification memory locations ; BE01 (0B0E0001) = beta version 1 ; BE02 (0B0E0002) = beta version 2 etc. ; 0703 (00070003) = release (YYWW), week 6 of 2007 ; NOTE: the PIC10F222 datasheet (DS41270D, page 41) states that we may only use the lowest four bits and we must program the ; upper eight bits as '1's. This means we can only use hexadecimal notation: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F. ; ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; ; ********************************************************************** ; * * ; * REMEMBER TO TURN ON CODE PROTECT * ; * * ; ********************************************************************** ; ; NOTE ! The PIC10F222 datasheet (DS41270D, page 41) states that the first 64 locations and the last location (Reset Vector) can ; always be read out, regardless of the code protection bit setting !!! ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; 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 bit spreading is achieved by 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. The benefit is that we ; can use "rlf" instructions to shift these 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. ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; Pinout ;------------------------------------------------------------------------------------------------------------------------------------- ; ; PIC10F222 (SOT23-6) ; ______________________________________ ; | \______/ | ; | | ; PWM output phase1 <<<< 1 ___| GP0/AN0/ICSPDAT GP3/NOT_MCLR/VPP |___ 6 not used ; | | ; | | ; | | ; Ground 2 ___| VSS VDD |___ 5 +3..5V ; | | ; | | ; | | ; PWM output phase2 <<<< 3 ___| GP1/AN1/ICSPCLK GP2/T0CLK/FOSC4 |___ 4 >>>> PWM output phase3 ; | | ; |______________________________________| ; ; ; ; ; ; ; PIC10F222 (DIL8/SO-8) ; __________________________________________ ; | \______/ | ; | | ; | | ; 1 ___| n/c GP3/NOT_MCLR/VPP |___ 8 not used ; | | ; | | ; | | ; | | ; +3..5V 2 ___| VDD VSS |___ 7 Ground ; | | ; | | ; | | ; | | ; PWM output phase3 <<<< 3 ___| GP2/T0CLK/FOSC4 n/c |___ 6 ; | | ; | | ; | | ; | | ; PWM output phase2 <<<< 4 ___| GP1/AN1/ICSPCLK GP0/AN0/ICSPDAT |___ 5 >>>> PWM output phase1 ; | | ; | | ; | | ; |__________________________________________| ; ; ; ; 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) ; ; ; The hardware design allows for the PIC to be programmed in-circuit (ICSP). ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; Editor Settings ;-------------------------------------------------------------------------------------------------------------------------------------- ; ; Bitstream Vera Sans Mono (size 8 for screen display, size 6 for printing) ; ; Tabsize: 8 characters ; ; Program code written with MPLAB IDE v8.30 from Microchip ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; PIC 12-bit core instruction set ;-------------------------------------------------------------------------------------------------------------------------------------- ; ; Mnemonic Description Function Status affected Instr.Cycles ; ; ADDWF f,d Add W and f W + f > d C, DC, Z 1 ; SUBWF f,d Subtract W from f f - W > d C, DC, Z 1 ; BCF f, b Bit clear f 0 > f ( b ) 1 ; BSF f, b Bit set f 1 > f ( b ) 1 ; BTFSC f, b Bit test, skip if clear skip if f ( b ) = 0 1(2)* ; BTFSS f, b Bit test, skip if set skip if f ( b ) = 1 1(2)* ; CLRF f Clear f 0 > f Z 1 ; CLRW Clear W 0 > W Z 1 ; INCF f,d Increment f f + 1 > d Z 1 ; INCFSZ f,d Increment f, skip if zero f + 1 > d, skip if 0 1(2)* ; DECF f,d Decrement f f - 1 > d Z 1 ; DECFSZ f,d Decrement f, skip if zero f - 1 > d, skip if 0 1(2)* ; GOTO k Goto address (k is nine bits) k > PC (9 bits) 1 ; CALL k Call subroutine PC + 1 > TOS, k > PC 2 ; RETLW k Return with literal in W k > W, TOS > PC 2 ; MOVLW k Move literal to W k > W 1 ; MOVF f,d Move f f > d Z 1 ; MOVWF f Move W to f W > f 1 ; SWAPF f,d Swap halves f f ( 0:3 ) > f ( 4:7) > d 1 ; RLF f,d Rotate left through carry C < 76543210 < C 1 ; RRF f,d Rotate right through carry C > 76543210 > C 1 ; COMF f,d Complement f .NOT. F > d Z 1 ; ANDLW k AND literal and W k .AND. W > W Z 1 ; ANDWF f,d AND W and f W .AND. F > d Z 1 ; IORLW k Inclusive OR literal and W k .OR. W > W Z 1 ; IORWF f,d Inclusive OR W and f W .OR. F > d Z 1 ; XORLW k Exclusive OR literal and W k .XOR. W > W Z 1 ; XORWF f,d Exclusive OR W and f W .XOR. F > d Z 1 ; NOP No operation 1 ; OPTION Load OPTION register W > OPTION Register 1 ; CLRWDT T Clear watchdog timer 0 > WDT (and prescaler) _TO , _PD 1 ; SLEEP Go into standby Mode 0 > WDT, stop oscillator _TO , _PD 1 ; TRIS f Tristate port f (only A,B,C!) W > I/O control register f 1 ; ; ; * = If the program counter (PC) is modified, or a conditional test is true, the instruction requires two cycles. The second ; cycle is executed as a NOP ; ; NOTE: Do not use two file operations (like CLRF/BCF/BSF...) on the SAME I/O-PORT (file registers are not affected) directly ; after one another in your program ! Because of the one command cache in combination with the read-modify-write ; behaviour of the PIC chips the result will be wrong ! ; ; Field description: ; ; f register file address (0x00 to 0x7F) ; w working register (accumulator) ; b bit address within an 8-bit file register ; k literal field, constant data or label ; d destination select, d = 0 means store result in w, d = 1 means store result in file register f (default is d = 1) ; PC program counter ; TO time-out bit ; PD power-down bit ; ; ; Subtraction: Carry = 1 result is positive or zero ; Carry = 0 result is negative (borrow) ; Addition: Carry = 1 result is > 255 (overflow) ; Carry = 0 result is <=255 ; ; The contents of the PCLATH register are unchanged after a RETURN or RETFIE instruction is executed ! The user must rewrite the ; contents of the PCLATH register for any subsequent subroutine calls or goto instructions (meaning: make sure page bits are set ; properly !) ; ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; Verify processor ;-------------------------------------------------------------------------------------------------------------------------------------- IFNDEF __10F222 MESSG "Processor-header file mismatch. Verify selected processor." ENDIF ;-------------------------------------------------------------------------------------------------------------------------------------- ; Configuration ;-------------------------------------------------------------------------------------------------------------------------------------- list p=10f222 ; directive to define processor radix dec ; all numbers are decimal unless stated otherwise ; errorlevel -219 ; suppress 'Invalid RAM location specified' warnings (editor warns unneededly about these ; addresses because of unused registers at the same locations in bank1 ; errorlevel -302 ; suppress 'not in register bank' warnings ; errorlevel -305 ; suppress 'default destination' warnings ; errorlevel -306 ; suppress 'crossing page boundary' warnings ; the '__CONFIG' directive is used to embed configuration data within .asm file. _MCLRE_ON EQU H'0FFF' _MCLRE_OFF EQU H'0FEF' _CP_ON EQU H'0FF7' _CP_OFF EQU H'0FFF' _WDT_ON EQU H'0FFF' _WDT_OFF EQU H'0FFB' _MCPU_ON EQU H'0FFD' _MCPU_OFF EQU H'0FFF' _IOFSCS_8MHZ EQU H'0FFF' _IOFSCS_4MHZ EQU H'0FFE' _IOSCFS_8MHZ EQU H'0FFF' ;Matches datasheet _IOSCFS_4MHZ EQU H'0FFE' ;Matches datasheet __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 ; !!! IMPORTANT COMPILING NOTE !!! ; ; Please note that in some versions of MPLAB IDE the option ; "configure/settings.../program loading/clear configuration bits upon loading a program" ; is checked ON by default ! ; ; Make sure this this setting is turned OFF when using the calibrated internal clock ! ; Otherwise the precision calibration will be lost ! ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; Name registers ;-------------------------------------------------------------------------------------------------------------------------------------- w EQU H'0000' ; used in instructions like decsfz f EQU H'0001' ; to indicate destination ;----- Register Files-------------------------------------------------- indf EQU H'0000' ; indirect file register tmr0 EQU H'0001' ; timer 0 module register pcl EQU H'0002' ; program counter (low byte) status EQU H'0003' ; status register fsr EQU H'0004' ; indirect data memory address pointer osccal EQU H'0005' ; oscillator calibration register gpio EQU H'0006' ; i/o port adcon0 EQU H'0007' ; ad-converter configuration register adres EQU H'0008' ; result of analog-to-digital conversion ;----- STATUS Bits ---------------------------------------------------- gpwuf EQU 7 not_to EQU 4 not_pd EQU 3 z EQU 2 dc EQU 1 c EQU 0 ;----- OPTION Bits ---------------------------------------------------- not_gpwu EQU 7 not_gppu EQU 6 t0cs EQU 5 t0se EQU 4 psa EQU 3 ps2 EQU 2 ps1 EQU 1 ps0 EQU 0 ;----- OSCCAL Bits ------------------------------------------------------ cal6 EQU 7 cal5 EQU 6 cal4 EQU 5 cal3 EQU 4 cal2 EQU 3 cal1 EQU 2 cal0 EQU 1 fosc4 EQU 0 ;----- GPIO Bits ----------------------------------------------------- gp3 EQU 3 gp2 EQU 2 gp1 EQU 1 gp0 EQU 0 ;----- ADCON0 Bits ----------------------------------------------------- ans1 EQU 7 ans0 EQU 6 chs1 EQU 3 chs0 EQU 2 go EQU 1 not_done EQU 1 adon EQU 0 ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; Constants definitions ;-------------------------------------------------------------------------------------------------------------------------------------- ; GPIO bits pwm1 EQU 0 ; pwm outputs pwm2 EQU 1 ; pwm3 EQU 2 ; unused EQU 3 ; ;-------------------------------------------------------------------------------------------------------------------------------------- ; Variable definitions (Hex 09-1F) ;------------------------------------------------------------------------------------------------------------------------------------- __MAXRAM H'1F' phasea EQU 0x09 ; sine wave duty cycle data (0..255, corresponding to 0%..100% duty cycle) phaseb EQU 0x0A ; phasec EQU 0x0B ; pointer EQU 0x0C ; pointer to duty cycle value in wave table (maximum address range = 1..253) loopcount EQU 0x0D ; obvious newa EQU 0x0E ; new wave table values newb EQU 0x0F ; newc EQU 0x10 ; wta EQU 0x11 ; wave table values wtb EQU 0x12 ; wtc EQU 0x13 ; out1 EQU 0x14 ; temporary storage for output values out2 EQU 0x15 ; lowvoltage EQU 0x16 ; bit0 of this register is set when power supply voltage is too low (see code for value) unused_17 EQU 0x17 ; unused_18 EQU 0x18 ; unused_19 EQU 0x19 ; unused_1A EQU 0x1A ; unused_1B EQU 0x1B ; unused_1C EQU 0x1C ; unused_1D EQU 0x1D ; unused_1E EQU 0x1E ; unused_1F EQU 0x1F ; ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- ; 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 memory page1 because we need all of the low memory for the sine table ;-------------------------------------------------------------------------------------------------------------------------------------- retlw d'0' 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 !) ;-------------------------------------------------------------------------------------------------------------------------------------- ; org h'0FF' ; This is last instruction location on the first memory half (PIC10F222), remember that all ; ; subroutine calls or computed jumps are limited to the first 256 program memory locations ! ; ; We can't use "ADDWF PCL,F","CALL","MOVWF PCL,F" or "BSF PCL,x" instructions to jump to an ; ; address > 255, but we can still use 'GOTO' and 'RETLW'. ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- 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 movlw b'00001001' ; we will use the analog-digital converter to monitor the power supply voltage: movwf adcon0 ; gp0 and gp1 digital, select internal reference voltage, no conversion now, adc on 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'11001100' ; value for no wake-up on pin change, no 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 ; ;--------------- ---------------------------------------------------------------------------------------------- decfsz loopcount,f ; wait a bit for the ad-converter capacitor to charge goto $-1 ; bsf adcon0,go ; start the ad-conversion, after 13 instruction cycles we can use the result decfsz loopcount,f ; wait for the conversion to finish goto $-1 ; movlw d'38' ; 255*(0.6 V/4.0V) = 38, we use hysteresis between turning on and off subwf adres,w ; clear carry when Vdd more than 4.0 Volts skpnc ; goto PIC_RESET ; leave LED off and do not start sine waves 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) incf loopcount,f ; make loopcount one for fast startup (was zero after loop) bcf lowvoltage,0 ; power supply is good ;--------------- ---------------------------------------------------------------------------------------------- MAINLOOP ; Fosc = 8 MHz ; Finstr = Fosc/4 = 2 MHz ; Fsine = 7.8 Hz ; number of instructions for one complete sine wave = 2000000 / 7.8 = 256410 instructions ; 3*77*1110=256410 instruction cycles therefore we use 3*77=231 points in one sine wave period ; we want as little instruction cycles per bit as possible for maximum resolution ; we have plenty program memory, so we will avoid loops when possible, this way we can weave in ; the table reads ;--------------- ---------------------------------------------------------------------------------------------- BIT1_3_5_7___ ; bit1 code is 3 instruction cycles shorter to compensate for the delay by a "goto" instruction btfsc lowvoltage,0 ; is power supply voltage high enough ? goto PIC_RESET ; no, go turn off LED and stop sine waves 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 bsf adcon0,go ; start the ad-conversion 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' ; 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 movlw d'51' ; 255*(0.6 V/3.0V) = 51 subwf adres,w ; set carry when Vdd is less than 3.0 Volts (set carry when adres >= 51) rlf lowvoltage ; set bit0 if power supply voltage is too low 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' ; 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'30' ; prepare the loop movwf loopcount ; clrwdt ; give the dog a bone 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' ; 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 ; goto BIT1_3_5_7___ ; go do another 74 bits ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- PIC_RESET org h'1FF' ; the processor reset vector, this code executes when a reset occurs ; movlw h'00' ; oscillator calibration value, on any device reset we will jump here ! ; MPLAB will normally prohibit reprogramming the oscillator calibration value. To trick MPLAB ; just select another device: Configure/Select Device.../PIC???, click 'Ok' to enable PM3 ; programmer to use new device and then program the whole memory of the PIC including the ; calibration value. After this change back to the PIC10F22x and program as normal. ;-------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------- end ; tell the assembler to stop