1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Bit rotation

Discussion in 'Oshonsoft' started by SwingeyP, Feb 10, 2014.

  1. SwingeyP

    SwingeyP Member

    Joined:
    Apr 26, 2010
    Messages:
    292
    Likes:
    2
    Location:
    Birmingham UK
    Hi Eric,

    I have asked Vladimir for a pointer as to whats going on with that first byte in the IEEE 754 conversion. He replied that he couldn't see a problem. I have explained exactly what I feel the problem is and sent him some code. I await a further reply. I have been messing around trying some way of just using LONG variables and maybe loosing a little resolution but this led to nothing :(

    Here is the code as it stands at the moment. There's a lot of tidying up to do. I can see lots of places where I could get rid of a few variables but for now it's working (almost).

    The current problem is a real show stopper for me. I'm not sure how I can get round it. Everything is working as it should if I could just get that SINGLE to be the same value as a LONG.

    Cheers - Paul
     

    Attached Files:

  2. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada
    The important thing is to decide what precision you want. 30 million multiplied by 35 is slightly over 1 billion. This requires 31-bit to represent. If you want the result to come out as 32-bit integer, the best precision you can get is 0.5 if you set up so that one digit represents 0.5 of your final units. This will give you lots of digits for big numbers, but will not be very precise for small ones. Frequency of 1 will be represnted as 34, frequency of 2 - as 68.5.

    Is this an acceptable precision for you? Then you can go integer road.

    How are you going to use these numbers, what are you doing with them?
     
  3. SwingeyP

    SwingeyP Member

    Joined:
    Apr 26, 2010
    Messages:
    292
    Likes:
    2
    Location:
    Birmingham UK
    Hi NorthGuy,

    It's a bit long winded t explain but if you look at the last code I posted above it's well commented and i'm sure you'll get the idea.
    The project is a Digital VFO using the AD9850 module.

    The SINGLE is because of a calculation to provide the frequency. The formula is on the AD9850 data sheet.

    Cheers - Paul
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada

    These are big numbers. You need 31-bit to represent them precisely. The float numbers only keep 24 bits, so you cannot use float if you need full precision.

    You need 32-bit arithmetic to deal with this. You need to be able to multiply two 32-bit numbers and get 64-bit result.

    I would suggest this: x*34.35973837 = x*34 +x*0.35973837

    As a first approximation you can use x*34. If the precision is not enough, then you calculate x*34 first, then you calculate x*0.35973837 and add it to x*34.

    How to calculate correction:

    x*0.35973837 = x*1545064534/4294967296

    x is 32-bit and 1545064534 is 32-bit. You multiply them and you get 64-bit integer. Division by 4294967296 is easy - you simply take the most significant 32 bits and discard the least significant 32 bits. Then you add your result to x*34 that you calculated earlier.

    If you do not have 32-bit by 32-bit multiplication, you can create it with 4 16-bit by 16-bit multiplications, or even 16 8-bit by 8-bit multiplications.
     
  6. jjw

    jjw Member

    Joined:
    Apr 16, 2012
    Messages:
    262
    Likes:
    15
    Location:
    Helsinki, Finland
    I don't know if this is a problem, but you can get at most 7 digit precision from a single variable, so 34.3597383 is not accurate to the last digits.
    If you need the four bytes from fout, could you convert fout to long and take each byte from it as Eric supposed.
    If you look the watch variables, same number as single in hex is different from long as hex

    Dim F as long
    Dim fout as single
    ----
    fout = 7000000*34.3597383
    F=fout
     
  7. jjw

    jjw Member

    Joined:
    Apr 16, 2012
    Messages:
    262
    Likes:
    15
    Location:
    Helsinki, Finland
    I replaced 34.359738 with 34.35974

    I checked this and it gives the right hex values in watch window:
    Code (text):

    Dim a As Single
    Dim fout As Long
    Dim w1 As Byte
    Dim w2 As Byte
    Dim w3 As Byte
    Dim w4 As Byte
    Dim i As Long
    For i = 0 To 3000 Step 1000
    a = 34.35974 * (7000000 + i) ' Oshonsoft makes here a small error, less than 0.5Hz at 7MHz
    fout = a
    w1 = fout.LB
    w2 = fout.HB
    w3 = fout.3B
    w4 = fout.4B
    Break
    Next i
    End                        
       
     
  8. ericgibbs

    ericgibbs Well-Known Member Most Helpful Member

    Joined:
    Jan 4, 2007
    Messages:
    21,189
    Likes:
    644
    Location:
    Ex Yorks' Hants UK
    hi jjw,
    I am also finding limitations with the FP Single.

    The manual states that if you prefix a Single with the hash sign '#' it will be available for Uart or LCD as a decimal value ASCII character string.

    I have added Hseropen etc, and then displayed the #fout string, above a certain value the upper characters become corrupted.

    I will try to determine what the limits of the Single are, will post later.

    Eric
     
  9. ericgibbs

    ericgibbs Well-Known Member Most Helpful Member

    Joined:
    Jan 4, 2007
    Messages:
    21,189
    Likes:
    644
    Location:
    Ex Yorks' Hants UK
    hi,
    This is a sample of the results so far.

    Using Hser suggests that #fout SINGLE value has a maximum of 9, 999,999
    I will run comparative tests on the Watch window values.

    Code (text):

    nxt1:
    fout = 100000
    Hserout #fout, CrLf

    fout = 1000000
    Hserout #fout, CrLf

    fout = 9999999
    Hserout #fout, CrLf

    fout = 10000000
    Hserout #fout, CrLf

    Goto nxt1
     
     

    Attached Files:

  10. SwingeyP

    SwingeyP Member

    Joined:
    Apr 26, 2010
    Messages:
    292
    Likes:
    2
    Location:
    Birmingham UK
    Hi JJW,
    That might just be the answer I'm after. I have just run it in simulation on my laptop here at work (can't do much here) and it looks about right.
    I'll try it on the actual setup and frequency counter when I get home later today. That is if the labs still standing. High winds here expected here in the UK today. :-(

    Dim fout1 As Single
    Dim fout As Long
    ad9850_freq = ad9850_mhz + ad9850_khz + hz
    fout1 = ad9850_freq * 34.35974 'reduce the accuracy?
    fout = fout1
     
  11. jjw

    jjw Member

    Joined:
    Apr 16, 2012
    Messages:
    262
    Likes:
    15
    Location:
    Helsinki, Finland
    You can probably use the original multiplier 34.359738.
    Oshonsoft Basic accepts it and with a quick test the accuracy seems to be little better , between -0.15Hz and -0.4Hz
     
  12. SwingeyP

    SwingeyP Member

    Joined:
    Apr 26, 2010
    Messages:
    292
    Likes:
    2
    Location:
    Birmingham UK
    I have no idea why this didn't work for me first time around. I tried this and it threw an error so I assumed I couldn't assign the single variable to a long. Thinking back it may have been because I had the resolution too large. What an idiot! :banghead: - Anyway this looks to be the solution to my problem but there is still something a little weird with he way OSHON handles large floating point numbers. It's beyond my expertise to understand why, i'll leave that to the GURU's :)

    Many thanks. Can't wait to get home now and try it for real :nailbiting:

    Cheers - Paul
     
  13. ericgibbs

    ericgibbs Well-Known Member Most Helpful Member

    Joined:
    Jan 4, 2007
    Messages:
    21,189
    Likes:
    644
    Location:
    Ex Yorks' Hants UK
    hi Paul,
    For a LONG which should be long enough [ pun] have you considered raising the 34.3597383 to say 343,597,383 [ == *10,000,000] and just multiplying by ad9850_mhz etc.....

    A LONG is 4-byte integers in the range 0 to 4,294,967,295)

    Code (text):

    ad9850_mhz = mhz * 1000000
    ad9850_khz = khz * 1000

    ad9850_freq = ad9850_mhz + ad9850_khz + hz
    fout = ad9850_freq * 34.3597383
     
  14. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada
    There's some loss of precision when you go through the single. I don't know if it is important to you or not.

    Code (C):
    #include <stdio.h>
     
    float x;
     
    void main() {
      int a = 1750000070; // 70 MHz * 35
      int b;
     
      x = a;
      b = x;
     
      printf("in: %d out: %d\r\n", a, b);
    }
    This produces:

    Code (text):
    in: 1750000070 out: 1750000128
     
  15. SwingeyP

    SwingeyP Member

    Joined:
    Apr 26, 2010
    Messages:
    292
    Likes:
    2
    Location:
    Birmingham UK
    BIG BIG BIG SMILEY FACE :):):):):):)

    Woo Hooo. I tried this method in the first place but couldn't get it to compile as looking back at what I've learned the multiplier 34.blah blah was too long and so I just made f0ut a SINGLE. This caused me no end of problems. Switching it back to LONG today and I'm a VERY happy bunny. I do still have a few issues around the lower band limit (not staying at 7.0) and also at power on sometimes the AD9850 doesn't get the frequency properly (I think this is mainly my poor electronics and I need pull ups etc etc). The resolution is fine for what I want and I can tune in 1hz steps :happy:

    I will start the vero-board prototype tomorrow.

    Many, many thanks to all that have helped me thus far. I have learned a lot, lost even more hair, and a lot of sleep. Don't you just love it.

    Eric,

    I have been documenting things as I've gone along to maybe put in an article (the how's and why's) - I'll probably need your help/approval when I get that far. There's a lot of code tidying and optimisation to do first.

    Thanks everyone


    Cheers - Paul
     
  16. SwingeyP

    SwingeyP Member

    Joined:
    Apr 26, 2010
    Messages:
    292
    Likes:
    2
    Location:
    Birmingham UK
    Ooooh my 4030B has arrived for the encoder / interrupt.
     

Share This Page