Menu

Sine and Cosine, in EEPROM. too

Anonymous
2014-03-30
2014-03-30
  • Anonymous

    Anonymous - 2014-03-30

    Hi Gang,

    Okay, here we go, a Sine and Cosine function in GC Basic, and the table is stored in EEPROM to save program space. Also, I tightened the code up a bit in general. As usual, there are lots of comments in case you want to make modifications of your own. As before, the functions themselves are quite small. It's the demo program and LCD printout that takes all the yammering.

    The arguments may be any positive, negative or zero value, of any size--this is completely general. The results are accurate to four decimal places.

    It just occurred to me that the Sine and Cosine functions here would be ideal for adding a circle subroutine to the graphic LCD stuff that's been appearing lately.

    Anyway, here you go:

    ;Implementing the Sine and Cosine functions in GC Basic
    ;Thomas Henry -- 3/29/2014
    
    ;This program demonstrates the Sine and Cosine functions
    ;by printing out their values for arguments from -720 degrees
    ;to 720 degrees, in one-degree increments. The actual
    ;functions themselves are very short. The main business of the
    ;demo program is tied up in formatting the results to
    ;appear neatly on an LCD.
    
    ;These are completely general purpose. Both Sine and Cosine
    ;can handle positive, negative or zero arguments of any
    ;arbitrary size.
    
    ;The values returned are valid to four decimal places,
    ;equivalent to most printed tables, and more than accurate
    ;enough for most engineering purposes.
    
    ;The values are returned as signed integers, scaled up by
    ;a factor of 10000. A lookup table stored in EEPROM memory
    ;is used for both, thanks to the cofunction relationship.
    ;The table maintains the most- and least-significant bytes
    ;separately. 183 bytes total of EEPROM are consumed.
    
    ;You might notice the casting, promotion and demotion of the
    ;various data types used. Some of these are implicit, while
    ;others are explicit.
    
    ;----- Configuration
    
    #chip 16F88, 8                  ;PIC16F88 running at 8 MHz
    #config mclr=off                ;reset handled internally
    #config osc=int                 ;use internal clock
    
    ;----- Constants
    
    #define LCD_IO      4           ;4-bit mode
    #define LCD_RS      PortB.2     ;pin 8 is LCD Register Select
    #define LCD_Enable  PortB.3     ;pin 9 is LCD Enable
    #define LCD_DB4     PortB.4     ;DB4 on pin 10
    #define LCD_DB5     PortB.5     ;DB5 on pin 11
    #define LCD_DB6     PortB.6     ;DB6 on pin 12
    #define LCD_DB7     PortB.7     ;DB7 on pin 13
    #define LCD_NO_RW   1           ;ground the RW line on LCD
    
    #define degree      223         ;ASCII code for degree mark
    
    ;----- Variables
    
    dim index, tabVal as byte
    dim i, sign as integer
    dim outStr as string
    
    ;----- Program
    
    dir PortB out                   ;all outputs to the LCD
    
    for i = -720 to 720             ;arguments from -720 to 720
      cls
      print "sin("                  ;print the label
      print i                       ;and the argument
      LCDWriteChar degree           ;then degree mark
      print ")="                    ;and closing parenthesis
      locate 1,0
      printTrig(sin(i))             ;print value of the sine
      wait 1 S
    
      cls                           ;do likewise for cosine
      print "cos("
      print i
      LCDWriteChar degree
      print ")="
      locate 1,0
      printTrig(cos(i))
     wait 1 S                       ;pause to view
    next i
    
    ;----- Subroutines
    
    function ref(in arg1 as integer) as integer
      ;create reference angle (0 to 90) for the argument
    
      if (arg1 > 270) then          ;Quadrant IV
        ref = 360 - arg1
      else
        if (arg1 > 180) then        ;Quadrant III
          ref = arg1 - 180
        else                        ;Quadrant II
          if (arg1 > 90) then
            ref = 180 - arg1
          else
            ref = arg1              ;Quadrant I by default
          end if
        end if
      end if
    end function
    
    ;-----
    
    function sin(in arg2 as integer) as integer
      ;get sine of angle
    
      if arg2 < 0 then              ;sine is an odd function,
        sign = -1                   ;so change sign of result
        arg2 = -1 * arg2            ;and negate negative angle
      else
        sign = 1                    ;else a positive angle
      end if
    
      arg2 = arg2 mod 360           ;reduce to 0 to 359 degrees
    
      if arg2 > 180 then
        sign = -1 * sign            ;negative in III and IV
      end if
    
      arg2 = ref(arg2)              ;get the reference angle
    
      index = [byte]arg2+1          ;index into the table
      readTable sineTab, index, tabVal
      sin = [integer]tabVal * 256   ;factor in MSB
      index = index + 91
      readTable sineTab, index, tabVal
      sin = sin + [integer]tabVal   ;factor in LSB
      sin = sign * sin              ;create final result
    end function
    
    ;-----
    
    function cos(in arg2 as integer) as integer
      ;get cosine of angle
    
      if arg2 < 0 then              ;cosine is an even function,
        arg2 = -1 * arg2            ;so negate negative angle
      end if
    
      arg2 = arg2 mod 360           ;reduce to 0 to 359 degrees
    
      sign = 1                      ;assume result is positive
      if arg2>90 and arg2<270 then
        sign = -1                   ;but negative in II and III
      end if
    
      arg2 = ref(arg2)              ;get the reference angle
      arg2 = 90 - arg2              ;use cofunction identity
      index = [byte]arg2+1          ;index into the table
    
      readTable sineTab, index, tabVal
      cos = [integer]tabVal * 256   ;factor in MSB
      index = index + 91
      readTable sineTab, index, tabVal
      cos = cos + [integer]tabVal   ;factor in LSB
      cos = sign * cos              ;create final result
    end function
    
    ;-----
    
    sub printTrig(in value as integer)
      ;print decently formatted trig results
    
      outStr = ""                   ;assume positive (no sign)
    
      if value < 0 then             ;handle negatives
        outStr = "-"                ;prefix a minus sign
        value = -1 * value          ;but work with positives
      end if
    
      select case value
        case 0:                     ;special case: zero
          outStr = "0.0000"
        case 10000:                 ;special case: +/- one
          outStr = outStr + "1.0000"
        case else                   ;all other cases
          outStr = outStr + "0."    ;format decimal fraction
    
          if value < 1000 then      ;left pad with zero if needed
             outStr = outStr + "0"
          end if
    
          outStr = outStr + str(value)
      end select
    
      print outStr
    end sub
    
    ;----- Data
    
    table sineTab store data
      ;Sine data for 0 through 90 degrees, scaled up by 10000.
      ;These are kept in EEPROM, as pairs of bytes. I generated
      ;these numbers using the spreadsheet in Open Office, then
      ;pasted them in here.
    
      ;Beginning of MSB's.
    
      0
      0
      1
      2
      2
      3
      4
      4
      5
      6
      6
      7
      8
      8
      9
      10
      10
      11
      12
      12
      13
      14
      14
      15
      15
      16
      17
      17
      18
      18
      19
      20
      20
      21
      21
      22
      22
      23
      24
      24
      25
      25
      26
      26
      27
      27
      28
      28
      29
      29
      29
      30
      30
      31
      31
      32
      32
      32
      33
      33
      33
      34
      34
      34
      35
      35
      35
      35
      36
      36
      36
      36
      37
      37
      37
      37
      37
      38
      38
      38
      38
      38
      38
      38
      38
      38
      38
      39
      39
      39
      39
    
      ;Beginning of LSB's
    
      0
      175
      93
      11
      186
      104
      21
      195
      112
      28
      200
      116
      31
      202
      115
      28
      196
      108
      18
      184
      92
      0
      162
      67
      227
      130
      32
      188
      87
      240
      136
      30
      179
      70
      216
      104
      246
      130
      13
      149
      28
      161
      35
      164
      35
      159
      25
      146
      7
      123
      236
      91
      200
      50
      154
      0
      98
      195
      32
      124
      212
      42
      125
      206
      28
      103
      175
      245
      56
      120
      181
      239
      39
      91
      141
      187
      231
      16
      53
      88
      120
      149
      175
      197
      217
      234
      248
      2
      10
      14
      16
    end table
    

    Thomas Henry

     
  • Anobium

    Anobium - 2014-03-30

    Very nice. If you agree I could add to the Help File.

     
  • Anonymous

    Anonymous - 2014-03-30

    Hi Anobium,

    By all means, feel free to use it if it would be helpful!

    Thomas Henry

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.