Copyright K.Unsworth and Unicorn Publications International 1990-2013 All Rights Reserved. Terms and Conditions.

;Maths functions

;for Home use only. NOT FOR COMMERCIAL USE

;clock switch works .







;3. The "__reset" label is the first label in the code section and must be    *

;   declared global. The Stack Pointer (W15) and the Stack Pointer Limit      *

;   register must be initialized to values that are past the run-time heap    *

;   space, so as to avoid corrupting user data. Initializing these registers  *

;   at the "__reset" label ensures that user data is not corrupted            *

;   accidentally. The __SP_init and __SPLIM_init literals are defined by the  *

;   linker. The linker automatically addresses above the run-time heap to     *

;   these symbols. Users can change the __SP_init and __SPLIM_init literals to*

;   suit their application.                                                   *

;                                                                             *

;4. A ".section <section_name>, <attributes>" directive declares a new section*

;   named "<section_name>" with an attribute list that specifies if the       *

;   section is located in Program Space(code), Uninitialized(bss) or          *

;   Initialized Data Space(data). Refer to the document "dsPIC 30F Assembler, *

;   Linker and Utilities User's Guide" for further details.                   *

;                                                                             *

;5. Initialize W registers: Using uninitialized W registers as Effective      *

;   Addresses(pointers) will cause an "Uninitialized W Register Trap" !       *

;                                                                             *

;6. The label "__T1Interrupt" is defined in the device linker script. The     *

;   label defines the starting location in program space of the Timer1        *

;   interrupt service routine (ISR).                                          *

;   Similarly, the linker script defines labels for all ISRs. Notice, that    *

;   the ISR label names are preceded by two underscore characters.            *

;   When users needs to write ISR code, they must use these labels after      *

;   providing them global scope. The linker will then place the ISR address in*

;   the respective interrupt vector table location in program space.          *

;   Context Save/Restore in ISRs can be performed using the double-word PUSH  *

;   instruction,PUSH.D. User can also make use of MOV.D, PUSH and PUSH.S      *

;   instructions. Refer dsPIC 30F 16-bit MCU Family Refernce Manual(DS70046)  *

;   for further details.                                                      *

;


       .equ __33fj256mc710, 1

       .include "p33fj256mc710.inc"


;*****************Configuration bits:**************************


      config __FWDT, FWDTEN_OFF              ;Turn off Watchdog Timer


;  config __CONFIG1, FNOSC_FRC & FWDTEN_OFF

;   internal rc oscilator on  and watch dog off


;  config __FOSC, FCKSM_CSECMD & IOL1WAY_OFF & OSCIOFNC_ON & POSCMD_NONE

;  clock switching on , multiple configs, i/o pins on, primary osc disabled


;  config __FOSCSEL, FNOSC_FRC & IESO_OFF

;  fast rc osc no pll ( yet), two speed osc off


;  set pll , tuning , clk div in main code then swap clocks


;from internet


 config __FOSCSEL, FNOSC_FRC

;  fast rc osc

 config __FOSC, FCKSM_CSECMD & OSCIOFNC_ON & POSCMD_NONE


; Clock Switching is enabled and Fail Safe Clock Monitor is disabled

; OSC2 Pin Function: OSC2 is Clock Output ( might need to change)

; Primary Oscillator Mode: Disabled


;Starts at 7.37 MHz with no PLL

;changes to 79.2MHz in code

;runs at 83.989 Mhz with chip i have.

;no time crytical apps so not important


;********Global Declarations: ***********************************************


       .global _wreg_init       ;Provide global scope to _wreg_init routine

                                ;In order to call this routine from a C file,

                                ;place "wreg_init" in an "extern" declaration

                                ;in the C file.


       .global __reset          ;The label for the first line of code.



;***************Constants stored in Program space**************************


       .section .const,psv

;       .palign 2                ;Align next word stored in Program space to an

                                ;address that is a multiple of 2


;  <0x0> =chr$(0)  put 0 at end of string to mark end

lcddata1:

  .ascii "UPI Func",<0x0>

lcddata2:

 .ascii "tion Gen ",<0x0>

lcddata3:

 .ascii  "123456789",<0x0>


;***************** variables in Near data memory (Lower 8Kb of RAM)*************


         .section .nbss, bss, near

; var1:     .space 2               ;Example of allocating 1 word of space for

                                  ;variable "var1".

intcounter:  .space 2    ;standard counter

   buffer:         .space 20               ;for ascii code    



 flags:   .space 2


.equ numberfound,0     ;used to diferentiate between zero and space on lcd

; .equ pb1f FLAGS,1

; .equ pb2f FLAGS,2

; .equ pb3f FLAGS,3

; .equ pb4f FLAGS,4


;********************constants for code************************


 .equ fcy,40000000     ;40 mips

 .equ  baudrate,9600     ;uart baud rate

 .equ  brval,((fcy/baudrate)/16)-1  ;value for setting uart



;*************Start of program**************



.text                               ;Start of Code section

__reset:

       MOV  #__SP_init, W15       ;Initalize the Stack Pointer

       MOV  #__SPLIM_init, W0      ;Initialize the Stack Pointer Limit Register

       MOV  W0, SPLIM

       NOP                       ;Add NOP to follow SPLIM initialization      

; reset all w register  this MUST be done

       CLR  W0

       MOV  W0, W14

       REPEAT  #12

       MOV  W0, [++W14]

       CLR  W14


;**************setup oscilator pll (my code)****************

;Set clock to 80Mhz = 40 MIPs

;IMPORTANT set PLL ratios before change of clock to PLL

 bclr CLKDIV,#6

 bclr CLKDIV,#7  ;PLL post =0 divide = 2

 mov  #43,w0   ;7.37/4*43=79.2275Mhz

 mov  w0,PLLFBD  ;PLL feed back divisor = 40 (38+2)


;from book

 MOV  #1,w0   ;frc with PLL, new nosc code

 

  MOV  #OSCCONH,W1  ;unlock code

 MOV  #0x78,W2

 MOV  #0x9A,W3

 MOV.B W2,[W1]   ;WRITE 0x78

 MOV.B W3,[W1]   ;WRITE 0x9A

 MOV.B W0,[W1]   ;now set type of clock

       

  MOV  #0x01,W0


 MOV  #OSCCONL,W1

 MOV  #0x46,W2

 MOV  #0x57,W3

 MOV.B W2,[W1]   ;WRITE 0x46

 MOV.B W3,[W1]   ;WRITE Ox9A


 MOV.B W0,[W1]   ;REQUEST CLOCK SWITCH

wait:

  BTSC OSCCONL,#OSWEN

;turn off bra for simulator. turn back on for real thing

;  BRA  wait   ;WAIT FOR SWITCH


;****************************************************************




      bra     numbertoascii


;*******************************************************************

;square root from internet.

;input NNNN.NNNN     w0.w1

;result NN.NN  w0

;or

;input .NNNNNNNN

;result .NNNN w0

;or

;input NNNNNNNN

;result NNNN w0



squareroot:

        push    w2

       push    w3

       push    w4

       push    w5

sqroot:

       mov.w   #0x8000,w3

       clr     w2

sqroot1:

       ior     w3,w2,w2

       mul.uu  w2,w2,w4

       sub     w1,w4,w4

       subb    w0,w5,w5

       bra     C,sqroot2

       xor     w3,w2,w2

sqroot2:

       lsr     w3,w3

       bra     NZ,sqroot1

       mov     w2,w0

       pop     w5

       pop     w4

       pop     w3

       pop     w2

       return



;****************************************************************

;arctan  +- 0.75 deg

;for z<1

;input w0.NNNN as fraction ie opp/adj <1

;output w0 degrees  NN.NN

;arctan(z)=z-(z^3/4.6) ( approx in radians *57.26 for degrees )

;to do arctan >1 do adj/opp and subtract it from 90 for answer.

;test for this before calling


arctan:

       push.d  w2

       push.d  w4

       mov     w0,w2           ;save z

       mul.uu  w2,w2,w4        ;w4:w5=z^2 w5=MSW

       mul.uu  w2,w5,w4        ;times by z again w5=MWS  z^3 in w5

       mov     #46,w4

       repeat  #17

       div.u   w5,w4           ;divide by 46. answer in w0

        mov     #10,w1

       mul.uu  w0,w1,w4        ;make it div by 4.6. w5=MSW w5 will be 0. max value of w4 14240

       sub     w2,w4,w0        ;w0=z-(z^3/4.6)

       mov     #58671,w1       ;57.296*1024 deg in a radian

       mul.uu  w0,w1,w4        ;w4:w5 = arctan(z)*1024 w5=MSW

       bclr    SR,#C           ;clear carry

       rrc     w5,w5           ;rotate down 2 bits

       bclr    SR,#C           ;clear carry

       rrc     w5,w5           ;now NN.NN

       mov     w5,w0           ;return degrees

       pop.d   w4

       pop.d   w2

       return


;******************************************************************

;arcsin

;arcsin(z)=pi/2-sqrt(1-z)*(1.57072881-0.2121144*z+0.0742610*z*z-0.0187293*z*z*z)

;for z<1

;input w0 .NNNN

;output w0 NN.NN in degrees



arcsin:

       push.d  w2

       push.d  w4

       push.d  w6  

       push.d  w8      

       mov     w0,w2

       mul.uu  w0,w0,w4        ;w5 holds MSW

       mov     w5,w6           ;save z^2

       mul.uu  w0,w6,w4        ;w5 holds MSW

       mov     w5,w7           ;z^3

       mov     #13901,w1       ;a1

       mul.uu  w0,w1,w4        ;a1*z  w5=MSW

       mov     w5,w8           ;w8=a1*z

       mov     #4867,w1        ;a2

       mul.uu  w1,w6,w4        ;a2*z^2 w5=MSW

       mov     w5,w9           ;w9=a2*z^2

       mov     #1227,w1        ;a3

       mul.uu  w1,w7,w4        ;a3*z^3  w5=MSW

        bclr    SR,#C           ;clear carry

       rrc     w5,w5           ;/2

       bclr    SR,#C           ;clear carry

       rrc     w8,w8           ;/2  

       bclr    SR,#C           ;clear carry

       rrc     w9,w9           ;/2     

       mov     #51470,w0       ;a0

       sub     w0,w8,w0        ;w0=w0-w8 w0=a0-a1*z

       add     w0,w9,w0        ;w0=w0+w9 w0=a0-a1*z+a2*z^2

       sub     w0,w5,w0        ;w0=w0-w5 w0=a0-a1*z+a2*z^2-a3*z^3

       mov     w0,w9           ;save in w9

       mov     #65535,w0       ;move 1 into w0 ( nearly 1 )

       sub     w0,w2,w0        ;w1=w1-w2  1-z

       clr     w1              ;clear w0

       rcall   squareroot      ;answer in w0 .NNNN

       mul.uu  w0,w9,w4        ;sqrt(1-z)*(a0....) w5=MSW . B.NNN here w9 half size due to rrc above

       mov     w5,w0           ;get MSW

       mov     #51472,w1       ;pi/2 *32768 ( 15 bit B.NNN

       sub     w1,w0,w0        ;w0=w1-w0  pi/2-sqrt(1....     B.NNN-B.NNN=B.NNN

       mov     #29335,w1       ;57.296*512 deg in a radian

       mul.uu  w0,w1,w4        ;w4:w5 = arctan(z)*256 w5=MSW

       mov     w5,w0           ;return degrees        


       pop.d   w8

       pop.d   w6

       pop.d   w4

       pop.d   w2

       return


;****************************************************************

;arccos(z)

;arccos(z)=pi/2-arcsin(z) in radians

;for z<1

;input w0 .NNNN

;output w0 NN.NN in degrees

arccos:

       push    w1

       rcall   arcsin

       mov     #90*256,w1      ;90 degrees in NN.NN format

       sub     w1,w0,w0        ;90 degrees-arcsin(z) in NN.NN format

       pop     w1

       return


;;********************************************************************************

;chr$(.NNNN)

;fraction as ascii  w0

;in w0=.NNNN output  buffer-> .AAAAAAAAAAAAAAAA  LSB first

fractiontoascii:


       push    w1

       push.d  w4

       push.d  w6


       mov     #buffer,w6

       mov     #10,w4

       mul.uu  w0,w4,w0        ;w1 holds value

       mov     #48,w5          ;0 ascii

       ior.b   w1,w5,[w6++]    ;shift out ascii to w6 ( buffer )    


       mul.uu  w0,w4,w0        ;drops the old value in w1 and takes the next tenth of w0

       ior.b   w1,w5,[w6++]    ;n=0-9 plus 48

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]

       mul.uu  w0,w4,w0

       ior.b   w1,w5,[w6++]


       pop.d   w6

       pop.d   w4

       pop     w1


       return


;*****************************************************************


.end


Maths Functions for pic24/dspic30/33

ARCSIN ARCCOS ARCTAN SQUAREROOT


In assembly


Download source here