Shop OBEX P1 Docs P2 Docs Learn Events
TACHYON O/S V3.0 JUNO - Furiously Fast Forth, FAT32+LAN+VGA+RS485+OBEX ROMS+FP+LMM+++ - Page 82 — Parallax Forums

TACHYON O/S V3.0 JUNO - Furiously Fast Forth, FAT32+LAN+VGA+RS485+OBEX ROMS+FP+LMM+++

17980828485109

Comments

  • D.P wrote: »
    completely confused now,

    #170 SPIWRB SPICE ok

    Probably not a problem but are you defaulted to decimal mode as in the last line you forced decimal mode with # ?

    Be aware too that the clock pulses from the SPIWR instructions are 50ns wide so hopefully your LA should see them normally.

  • Regarding loading PASM objects I have been meaning to fully implement this by way of letting the kernel assembler the PASM source and storing the binary file in EEPROM or SD card files. The idea is that at run-time you can load the module by name into a cog. BTW, there really isn't any room left in a Tachyon cog anyway, even a stripped down one and there is normally about 20 longs reserved for RUNMOD modules.

    I have to finish off my assembler first which is mostly working fine and then it's simply a matter of filing the binary away and having the load method available.Should be fun.
  • Regarding loading PASM objects I have been meaning to fully implement ...

    Sounds interesting Peter. I'll keep an eye out for this.
  • Fixed the little bug with &00.xx.xx.xx as the flag that forced decimal byte mode was always overwritten by the assembled number but if the first . group was zero then it reset the flag! :)
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2016-05-08 14:37
    D.P wrote: »
    completely confused now,

    #170 SPIWRB SPICE ok


    V2.8 has a few extra enhancements to speed things up a bit more plus I've made the SPIWR clock pulse 100ns wide instead of 50ns but still with the same 4MHz cycle time so you should be able to see that on your scope and also relaxes any timing issues with 50ns pulses.

  • Okay I will get back to this driver today and test this build on my end, thanks
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2016-05-08 15:59
    D.P wrote: »
    Okay I will get back to this driver today and test this build on my end, thanks

    Hang off a bit, I've stuffed something up in the kernel and can't seem to see it and I'm bleary eyed now. Let you know as soon as I rectify it, whatever it is.....

    That's the trouble with editing the kernel straight out of dropbox, it's all bleeding edge stuff.

  • MJBMJB Posts: 1,235
    Regarding loading PASM objects I have been meaning to fully implement this by way of letting the kernel assembler the PASM source and storing the binary file in EEPROM or SD card files. The idea is that at run-time you can load the module by name into a cog. BTW, there really isn't any room left in a Tachyon cog anyway, even a stripped down one and there is normally about 20 longs reserved for RUNMOD modules.

    I have to finish off my assembler first which is mostly working fine and then it's simply a matter of filing the binary away and having the load method available.Should be fun.
    @Peter, it would also be great to not only be able to load COGlets,
    but also to compile new RUNMODs on the fly.
    Like now I need a little RUNMOD to speed up a ILI9341 LCD display -
    since it is connected in 4-wire mode (with extra C/D line and 8 instead 9 bit mode)
    the runmod you use for the QVGA display does not do the job.
    I can of course change it and recompile the kernel, but dynamic RUNMODs would be great as well.


  • MJB wrote: »
    Regarding loading PASM objects I have been meaning to fully implement this by way of letting the kernel assembler the PASM source and storing the binary file in EEPROM or SD card files. The idea is that at run-time you can load the module by name into a cog. BTW, there really isn't any room left in a Tachyon cog anyway, even a stripped down one and there is normally about 20 longs reserved for RUNMOD modules.

    I have to finish off my assembler first which is mostly working fine and then it's simply a matter of filing the binary away and having the load method available.Should be fun.
    @Peter, it would also be great to not only be able to load COGlets,
    but also to compile new RUNMODs on the fly.
    Like now I need a little RUNMOD to speed up a ILI9341 LCD display -
    since it is connected in 4-wire mode (with extra C/D line and 8 instead 9 bit mode)
    the runmod you use for the QVGA display does not do the job.
    I can of course change it and recompile the kernel, but dynamic RUNMODs would be great as well.

    Yes, this is part of what the assembler does of course, allowing RUNMODs to be compiled at runtime as well as larger cogjets which are filed away in EEPROM or SD.

    BTW, I thought I had a problem with the current kernel but it seems sleepy fingers turned on serial parity unnoticed !@#$^%#

  • MJBMJB Posts: 1,235
    edited 2016-05-09 22:58
    ...
    Yes, this is part of what the assembler does of course, allowing RUNMODs to be compiled at runtime as well as larger cogjets which are filed away in EEPROM or SD.

    Hi @Peter,

    the dynamic definition of RUNMODs could look like this:
    defMOD [SSD]
                corg     _RUNMOD                  '  could be automatic 
    {HELP SSD ( send cnt --  )  ( A: miso mosi sck )
      SSD module added for fast SSD2119 SPI operations
      COGREGS: 0=sck 1=mosi 2=miso 3=cnt 4=mode }
    _SSD
    SSDREP  mov     X,tos + 1
            shl     X,# 7         ' left justify but leave msb zero (control byte)
            call    # SSD8
            call    # SSD8D
            call    # SSD8D
            djnz    tos,# SSDREP
            jmp     # DROP2
    
    SSD8D   or      X,# 1           ' move 1 into msb = data
            ror     X,# 1
    SSD8    andn    OUTA,scs  ' chip select low
            mov     R1,scnt
    SSDlp   andn    OUTA,sck  ' clock low
            shl     X,# 1 wc    ' assume msb first
            muxc    OUTA,mosi    ' send next bit of data out
            or      OUTA,sck    ' clock high
            djnz    R1,# SSDlp
            or      OUTA,scs  ' chip select high
    SSD8D_ret
    SSD8_ret        ret
    ;
    
    which creates a new word [SSD], runs the assembler and puts the assembled code into the body.
    When executed the [SSD] word just executes (defMOD) which calls LOADMOD with the length of the runmod which is stored at the beginning of the PASM code and then the address of the code.

    So no extra handling of the PASM is needed, just stored in word space.

    Addit: and this would be great for playing with PASM as well


  • D.P wrote: »
    Okay I will get back to this driver today and test this build on my end, thanks

    Hang off a bit, I've stuffed something up in the kernel and can't seem to see it and I'm bleary eyed now. Let you know as soon as I rectify it, whatever it is.....

    That's the trouble with editing the kernel straight out of dropbox, it's all bleeding edge stuff.

    Uh yes maybe if I had sent up the Logic Analyzer CAPTURE TIMING correctly I wouldn't have wasted you time.

    Works great, less filling

    dp

  • Okay so the chip I'm interfacing with (MAX31865) requires a 100 ns MIN lo and hi clock hold time.

    Logic analysis shows kernel:
    Propeller .:.:--TACHYON--:.:. Forth V28160508.2200
    
    running SPIWRB at a clock lo/hi hold times of between 40 and 80 ns and SPIRD clock hold times of between 120 and 80 ns.

    Not even space in the kernel for a few NOPs, sigh
  • ElectrodudeElectrodude Posts: 1,621
    edited 2016-05-10 22:01
    D.P wrote: »
    Okay I will get back to this driver today and test this build on my end, thanks

    Hang off a bit, I've stuffed something up in the kernel and can't seem to see it and I'm bleary eyed now. Let you know as soon as I rectify it, whatever it is.....

    That's the trouble with editing the kernel straight out of dropbox, it's all bleeding edge stuff.

    Why don't you use Git or something? You get complete version history, you can tag an older commit as being stable while having bleeding-edge commits on top, and it can easily show you what you've changed between versions.
  • D.P wrote: »
    Okay I will get back to this driver today and test this build on my end, thanks

    Hang off a bit, I've stuffed something up in the kernel and can't seem to see it and I'm bleary eyed now. Let you know as soon as I rectify it, whatever it is.....

    That's the trouble with editing the kernel straight out of dropbox, it's all bleeding edge stuff.

    Why don't you use Git or something? You get complete version history, you can tag an older commit as being stable while having bleeding-edge commits on top, and it can easily show you what you've changed between versions.

    Yes, Git is great when used with a nice and simple GUI front-end, we use SmartGIT which is Linux, Mac and Doze compatible, free for non-commercial projects! $100.00 for a full up license.

  • ElectrodudeElectrodude Posts: 1,621
    edited 2016-05-10 22:10
    D.P wrote: »
    D.P wrote: »
    Okay I will get back to this driver today and test this build on my end, thanks

    Hang off a bit, I've stuffed something up in the kernel and can't seem to see it and I'm bleary eyed now. Let you know as soon as I rectify it, whatever it is.....

    That's the trouble with editing the kernel straight out of dropbox, it's all bleeding edge stuff.

    Why don't you use Git or something? You get complete version history, you can tag an older commit as being stable while having bleeding-edge commits on top, and it can easily show you what you've changed between versions.

    Yes, Git is great when used with a nice and simple GUI front-end, we use SmartGIT which is Linux, Mac and Doze compatible, free for non-commercial projects! $100.00 for a full up license.

    Better yet, normal Git is free and actually has a usable interface! :)
  • D.PD.P Posts: 790
    edited 2016-05-10 22:48
    Here are all the pertinent times for the MAX31865, I may have to bit bang this interface?

    Data to SCLK Setup tDC (Notes 8, 9) 35 ns
    SCLK to Data Hold tCDH (Notes 8, 9) 35 ns
    SCLK to Data Valid tCDD (Notes 8, 9, 10) 80 ns
    SCLK Low Time tCL (Note 9) 100 ns
    SCLK High Time tCH (Note 9) 100 ns
    SCLK Frequency tCLK (Note 9) DC 5.0 MHz
    SCLK Rise and Fall tR, tF (Note 9) 200 ns
    CS to SCLK Setup tCC (Note 9) 400 ns
    SCLK to CS Hold tCCH (Note 9) 100 ns
    CS Inactive Time tCWH (Note 9) 400 ns
    CS to Output High-Z tCDZ (Notes 8, 9) 40 ns
    Address 01h or 02h Decoded to
    DRDY High tDRDYH After RTD register read access (Note 9) 50 ns
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2016-05-10 23:45
    Don't worry, I've gleaned some longs from the kernel last night and now I can put those two extra instructions in to pad out the clock pulse to 100ns at the same frequency, much better than time wasting nops. I will make the change right now.
    Latest SPIWR - 100ns high, 150ns low = 4MHz

    Just confirmed this all works with a complete network build which uses the SPI instructions for the WIZnet chips.
  • Okay nice!, thx. I'll check this out later and post up the results.
  • Could someone please provide some guidance on how to win back some RAM in T2.7? Aside from "write better code" :)
    I have RECLAIM ed and went from 300 -->1600 bytes free, but I fear I will need more. Already using a SMALL extend.fth
    I have extend, a board-driver file, SD, Easyfile, and some tools. Still have to work to the app itself.
    How can I put the dictionary up to EEPROM ? Can the uSD be used to store the dictionary ?
    Thanks in advance!
  • D.PD.P Posts: 790
    edited 2016-05-11 07:17
    @PaulRowntree, Peter will have to comment.

    @Peter, well SPIRD is showing 80ns low clock hold times, SPIWR timings look great. Screen%20Shot%202016-05-10%20at%2011.36.58%20PM.png
  • Could someone please provide some guidance on how to win back some RAM in T2.7? Aside from "write better code" :)
    I have RECLAIM ed and went from 300 -->1600 bytes free, but I fear I will need more. Already using a SMALL extend.fth
    I have extend, a board-driver file, SD, Easyfile, and some tools. Still have to work to the app itself.
    How can I put the dictionary up to EEPROM ? Can the uSD be used to store the dictionary ?
    Thanks in advance!

    Assuming you have a 64k eeprom you would load eewords.fth in after easy file then run COMPACT then backup. All the dictionary up to that point will now be stored in eeprom but all further words will still be stored in ram in regular dictionary so you now have a hybrid dictionary. You won't be able to forget any words in the eeprom so if you need to redo any of this stuff just start again from COLD. No need to run reclaim either. This is how I get my networking layers squeezed in

  • MJBMJB Posts: 1,235
    edited 2016-05-11 08:25
    Could someone please provide some guidance on how to win back some RAM in T2.7? Aside from "write better code" :)
    I have RECLAIM ed and went from 300 -->1600 bytes free, but I fear I will need more. Already using a SMALL extend.fth
    I have extend, a board-driver file, SD, Easyfile, and some tools. Still have to work to the app itself.
    How can I put the dictionary up to EEPROM ? Can the uSD be used to store the dictionary ?
    Thanks in advance!
    you can file in EEWORDS.fth which puts dictionary in upper EEPROM if you have a 64k EEPROM
    this frees around 9k IIRC.
    You can also specify in EXTEND which modules to exclude (e.g. PWM ...)
    this is set up with a long before loading EXTEND (see comments module loader in EXTEND)
    I use this a bit more verbous version. Unfortunately I did not work out all dependencies between modules,
    which would make it even easier to use.
    Just comment / uncomment the desired modules and load before EXTEND.
    \ Extend module loader load definition
    \ for MJB webserver
    \ to save some space some modules are not included
     
    \ align to a byte before long
    4  codes W@ OVER 1- 3 AND ANDN OVER 1- 3 AND + codes W! GRAB CREATE mod2load 0 ,  \ collects the bitfield of the modules to be loaded
    4  codes W@ OVER 1- 3 AND ANDN OVER 1- 3 AND + codes W! GRAB CREATE modloaded 0 , \ collects the bitfield of the modules that have been loaded
    
    names W@  \ save on stack for restore later
    codes W@  \ "
    
    \ used to define the module table below
    : SETMOD ( id <name> -- )             \ the <name> is only for comment purposes and ignored
        [COMPILE] GRAB                        \  make id available on stack
        mod2load @ OR mod2load !           \  set the id bits in mod2load
        [COMPILE] \                               \  consume and ignore the module <name> from the input line
        ;   
    BL names W@ C@++ + SET           \ make it IMMEDIATE
    
    
    {
    The following table gives the modules that are required for a certain feature
    multiple dependencies are possible, the OR of all active (uncommented) lines defines
    what gets loaded.    
    Within EXTEND all required modules need to precede the module using them ( as usual )
     
    before setting up the table we will start by defining the modules - which will take some time
    and will require some restructuring as well
    
    }
    \ from Peter
    { Create an INCLUDE pseudo-constant before loading EXTEND.fth to specify options
    : INCLUDE
    \  .._.....I.Smile_ARR.MSSNHP_PCLOM.....
    \  .._.....T.DAT_NET.APEUEW_IHORA.....
    \  .._.....C.CNR_SPC.PRRMXM_NRCGT.....
    \  33_2222222222_1111111111_0000000000
    \  10_9876543210_9876543210_9876543210
     %00_0000000001_1100000100_1101100000
     }
    
    \  ------- e.g. to include PWM in the build uncomment line 10 PWM in  modules table -------
    \
    \         33_2222222222_1111111111_0000000000
    \         10_9876543210_9876543210_9876543210                                           
    \         .._.....I.Smile_ARR.MSSNHP_PCLOM.....
    \         .._.....T.DAT_NET.APEUEW_IHORA.....
    \     .._.....C.CNR_SPC.PRRMXM_NRCGT.....              
    \      3            2             1             0
    \         10_9876543210_9876543210_9876543210
    \       %00_0000000000_0000000000_0000000001  SETMOD BASICS   \  0
    \       %00_0000000000_0000000000_0000000001  SETMOD BASICS   \  1
    \       %00_0000000000_0000000000_0000000001  SETMOD BASICS   \  2
    \       %00_0000000000_0000000000_0000000001  SETMOD BASICS   \  3
    \       %00_0000000000_0000000000_0000000001  SETMOD BASICS   \  4
            %00_0000000000_0000000000_0000100001  SETMOD MAT      \  5     \ MATHS_FUNCTIONS
            %00_0000000000_0000000000_0001000001  SETMOD ORG      \  6     \ FIXED_POSITION_VARIABLES
            %00_0000000000_0000000000_0010000001  SETMOD LOC      \  7     \ LOCAL VARIABLES
            %00_0000000000_0000000000_0100000001  SETMOD CHR      \  8     \ CHARACTER_OUTPUT
            %00_0000000000_0000000000_1000000001  SETMOD PIN      \  9     \ PIN_I/O_OPERATIONS
    \       %00_0000000000_0000000001_0000000001  SETMOD PWM      \ 10     \ PWM 32 chan 8 bit 7.8kHz
            %00_0000000000_0000000010_0000000001  SETMOD HEX      \ 11     \ HEX FILE LOAD & DUMP
            %00_0000000000_0000000100_0000000001  SETMOD NUM      \ 12     \ NUMBER_PRINT_FORMATING
    \       %00_0000000000_0000001000_0000000001  SETMOD SER      \ 13     \ PBASIC_STYLE_SERIAL_I/O
            %00_0000000000_0000010000_0000000001  SETMOD SPR      \ 14     \ EXAMINE_SPECIAL_PURPOSE_REGISTERS
            %00_0000000000_0000100000_0000000001  SETMOD MAP      \ 15     \ Memory Map Reporting
    \       %00_0000000000_0001000000_0000000001  SETMOD BASICS   \ 16
            %00_0000000000_0010000000_0000000001  SETMOD RTC      \ 17     \ Virtual RTC words
            %00_0000000000_0100000000_0000000001  SETMOD REP      \ 18     \ COMPILER REPORTING
            %00_0000000000_1000000000_0000000001  SETMOD ANS      \ 19     \ ANSI_TERMINAL
            %00_0000000001_0000000000_0000000001  SETMOD STR      \ 20     \ STRINGS
    \       %00_0000000010_0000000000_0000000001  SETMOD SAN      \ 21     \ SAN_FILTER
    \       %00_0000000100_0000000000_0000000001  SETMOD ADC      \ 22     \ MCP3208_8_channel_ADC
    \       %00_0000001000_0000000000_0000000001  SETMOD BASICS   \ 23
            %00_0000010000_0000000000_0000000001  SETMOD ITC      \ 24     \ INTERTASK_COMMUNICATIONS
    \       %00_0000100000_0000000000_0000000001  SETMOD BASICS   \ 25
    \       %00_0001000000_0000000000_0000000001  SETMOD BASICS   \ 26
    \       %00_0010000000_0000000000_0000000001  SETMOD BASICS   \ 27
    \       %00_0100000000_0000000000_0000000001  SETMOD BASICS   \ 28
    \       %00_1000000000_0000000000_0000000001  SETMOD BASICS   \ 29
    \       %01_0000000000_0000000000_0000000001  SETMOD BASICS   \ 30
    \       %10_0000000000_0000000000_0000000001  SETMOD BASICS   \ 31
    
    \  now mod2load contains the mask for all EXTEND modules to be loaded
    
    mod2load @ . CR
    2DROP
    \ .S
    \ codes W!  \ release code and name - vector not yet released - not tested yet - is a little tricky
    \ names W!
    \ FORGET SETMOD  \ SETMOD not needed any more
    
    { output after loading the above from filing in EXTEND.fth
    
    0250      INCLUDING #9 PIN_I/O_OPERATIONS
    0405      INCLUDING #8 CHARACTER_OUTPUT
    0465      INCLUDING #6 FIXED_POSITION_VARIABLES
    0494      INCLUDING #5 MATHS_FUNCTIONS
    0581      INCLUDING #12 NUMBER_PRINT_FORMATING
    0693      INCLUDING #19 ANSI_TERMINAL
    0839      INCLUDING #20 STRINGS
    1115      INCLUDING #14   EXAMINE_SPECIAL_PURPOSE_REGISTERS
    1118      INCLUDING #15   Memory Map Reporting
    1425      INCLUDING #11 HEX FILE LOAD & DUMP
    1428      INCLUDING #18 COMPILER REPORTING
    
      Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
    Clock frequency = 80,000,000
    NAMES:  $6177...7471 for 4858 (2436 bytes added)
    CODE:   $0000...293C for 5698 (4128 bytes added)
    CALLS:  0590 vectors free
    RAM:    14395 bytes free
    
    }
    ." End of Extend Module Loader"
    
    
    
  • Look in the dropbox folder and find NETBUILD.FTH and just load that first from COLD before EXTEND. Otherwise you could just define SMALL before you load EXTEND:
    CREATE SMALL
    <load EXTEND.FTH>
    <load PCB defs>
    <load SDCARD.FTH>
    <load EASYFILE.FTH>
    <load EEWORDS.FTH>
    <run COMPACT and BACKUP>
    Now you have about 10k free or so.
  • The 80ns low clock times in SPIRD are a problem for the MAX31865, 100ns MIN. I guess I wasn't clear above. Gonna hook the chip to my Arduino and capture the timings to see what they use.
  • That is great, thanks Peter, MJB. 10K should do it nicely. This is an impressive suite; I just find it frustratingly slow to develop code to do any type of math ... but that is what the learning is for.
  • D.P wrote: »
    The 80ns low clock times in SPIRD are a problem for the MAX31865, 100ns MIN. I guess I wasn't clear above. Gonna hook the chip to my Arduino and capture the timings to see what they use.

    I will see if I can stretch the time on that part of it too.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2016-05-12 00:39
    D.P wrote: »
    The 80ns low clock times in SPIRD are a problem for the MAX31865, 100ns MIN. I guess I wasn't clear above. Gonna hook the chip to my Arduino and capture the timings to see what they use.

    I don't think your LA is very precise, I've got both the Digiview DV3100 and a Rigol MSO1104Z and the read timing is 100ns low and 150ns high vs the write timing which is 100 ns high and 150ns low. Does the MAX31865 respond?

    BTW, Since the SPI instructions simple toggle the clock line you could try setting clock high prior to a read and see how that goes.
  • That is great, thanks Peter, MJB. 10K should do it nicely. This is an impressive suite; I just find it frustratingly slow to develop code to do any type of math ... but that is what the learning is for.

    If you can give me an example of what you are trying to do I might be able to suggest a few ways of going about it or look at adding some enhancements if necessary. When I implement cogjects I may have FP in a cog but not for myself though as I haven't come across any application where scaled integers wouldn't work. Remember that some mixed operators produce a 64-bit result, there's plenty of range there.
  • D.P wrote: »
    The 80ns low clock times in SPIRD are a problem for the MAX31865, 100ns MIN. I guess I wasn't clear above. Gonna hook the chip to my Arduino and capture the timings to see what they use.

    I don't think your LA is very precise, I've got both the Digiview DV3100 and a Rigol MSO1104Z and the read timing is 100ns low and 150ns high vs the write timing which is 100 ns high and 150ns low. Does the MAX31865 respond?

    BTW, Since the SPI instructions simple toggle the clock line you could try setting clock high prior to a read and see how that goes.

    Alright then I just have a saleae 8 LA that will do 50Ms/s so you are probably right, again :) I will keep poking it, here is the arduino timings. Seems they run it at 1Mhz but the datasheet says the chip is good to 5Mhz.

    Also from the CS low to clock is 2 us which I mimic by manually setting CS

    amaxtime.png
    2832 x 576 - 107K

  • If you can give me an example of what you are trying to do I might be able to suggest a few ways of going about it or look at adding some enhancements if necessary. When I implement cogjects I may have FP in a cog but not for myself though as I haven't come across any application where scaled integers wouldn't work. Remember that some mixed operators produce a 64-bit result, there's plenty of range there.

    That is very kind of you, but it reveals many warts. OK. I have written an atan2 routine based on a SPIN polynomial approximation from CessnaPilot. This is one part of a sailboat autopilot. I tweaked it to give sub-degree accuracy in 150 us, but in the end, after too much coding time, I am going to go back to uSD tables because I need several other tabulated functions, and it will take less Prop memory. Plus, the polynomial shows much larger errors near 45 degrees.
    TACHYON
    [~
    {  ATAN2 : to be loaded after extend.fth }
    { 20160508 : created to test CessnaPilot's SPIN routine in FORTH  Works with x,y values of ranging -5000 to +5000.  Bigger is better
    - gives approximately 0.2 degree accuracy, 0.5 degree worst case
    
    }
    FORGET ATANTEST.fth
    
    pub ATANTEST.fth    ." ATAN Test Codes 20160508 " ;
    
    { atan2 links
    CessnaPilot's post on Propeller forum gave formulas, not sure where (s)he got them
        http://forums.parallax.com/discussion/115008/how-to-compute-atan2-with-integers-and-of-course-quickly
    Roman Black's site showed how to handle quadrants more efficiently using 'negflags' instead of nested conditions
          http://www.romanblack.com/integer_degree.htm
    }
    pub (atan2) ( a b -- 10*Angle )      \ calculates   36670*ab/(64a^2 + 17b^2)  a,b are positive (ie first quadrant)
                                         \ this case of CessnaPilots code is for ABS(Y) <= ABS(X)
    
        2DUP DUP * DUP 4 SHL +           \ ( -- a b a 17b^2 )
        SWAP DUP * 6 SHL +               \ ( -- a b 17b^2+64a^2 )
        >R * 36670 R> */                 \ pop the denominator over to the return stack, calc the numerator, bring it back
        ;
    
    pub (at2ax) ( x y -- x' y' )         \ if x or y =0, set to one to avoid ambiguity and singularities in (atan2)
        DUP 0= IF DROP 1 THEN
        SWAP
        DUP 0= IF DROP 1 THEN
        SWAP
        ;
    pub (at2qd) ( x y -- negflags )      \ quad 1 is (++), going CCW  (x,y) are never zero  ( x=bit 0, y=bit 1; 1=negative 0 = positive )
        0< IF 2 ELSE 0 THEN              \ quad 1 = (++) negflags = 0
        SWAP                             \ quad 2 = (-+) negflags = 1
        0< IF 1 ELSE 0 THEN              \ quad 3 = (--) negflags = 3
        +                                \ quad 4 = (+-) negflags = 2
        ;
    
    pub atan2 ( x y -- 10*angle )        \ calculates angle in tenths of degrees    ranges from 0-3600, takes ~150 us
        (at2ax)                          \ avoid singularities of X=0 or Y=0 by replacing 0 with +1
        2DUP (at2qd) >R                  \ get the negflags that identify quadrants, push negflags to Return stack
    
        SWAP ABS SWAP ABS 2DUP           \ ( -- |x'| |y'| |x'| |y'| )  calcs in (atan2) are always (++)
    
        > IF (atan2) ELSE SWAP (atan2) NEGATE 900 + THEN   \ (atan2) does the heavy lifting
    
        R>                              \ bring back negflags
        SWITCH                          \ SWITCH cases are by quadrants, but the values are not std 1-4 indices
    \   0 CASE BREAK                    \ (++)      no need to do this quadrant
        1 CASE NEGATE 1800 + BREAK      \ (-+)
        2 CASE NEGATE 3600 + BREAK      \ (+-)
        3 CASE 1800 + BREAK             \ (--)
        ;
        
    pub PitchRoll ( ax ay az -- pitch roll )  \ angles in tenths of a degree
        DUP >R atan2 SWAP R> atan2 ;
    
    pri Testatan2 ( n -- )              \ do n iterations of (x,y) with a limits of 5000 to -5000
        0 DO 5000 -5000 GETRND DUP . SPACE 5000 -5000 GETRND DUP . SPACE atan2 . CR LOOP ;
    
    pri Lapatan2 ( n -- )
        0 lap DO 5000 -5000 GETRND 5000 -5000 GETRND atan2 DROP LOOP lap .lap ;
    
    ]~
    END
    
    
Sign In or Register to comment.