Go Down

Topic: Converting Decimal to Hex (Read 305 times) previous topic - next topic

Callum_Austin11

Hi all,
The problem I have is programming a synthesizer using hex commands. Now, the user will input a desired frequency down to 0.5mhz steps. So for example 13,051.5 MHz. Now that number needs to be divided by 50 to get the number that needs to be converted to hex to actually program the synth.

So 13,051.5 divided by 50 would be 261.03. However that number needs splitting so that the 261 can be converted to hex as a separate integer. The hex number for 261 is 105.
Then the decimal 0.03 needs turning into a fraction. So 0.03/1 * 1000/1000 = 30/1000
The numerator and denominator needs turning into a hex as well. So 30 would 1E in hex and 1000 would be 3E8.
Then these hex values need to be sent as;
0x105
0x1E
0x3E8

Can anyone help me turn this into a code? Would be extremely helpful as this is confusing the hell out of me. Keep in mind the inputted frequency can be different in between 13,000MHz and 20,000MHz. Many thanks

pcbbc

#1
Jun 30, 2020, 05:27 pm Last Edit: Jun 30, 2020, 05:33 pm by pcbbc
Formats such as "hex", "decimal" and "binary" are number formats for displaying data in a human readable form.  For example in ASCII, or some other character encoding.

When a number is stored in an integer they don't have a "format".  They are just a sequence of bytes which represent an integer.

Quote
261 can be converted to hex as a separate integer
So that sentence doesn't really make any sense.

The key question here is how are the integer values (which you already have, or can calculate) are being sent to the synthesizer?

Are being sent as human readable text over a serial connection?
If so, yes - some format conversion is required from integer to ASCII.

Are they being sent as raw bytes of data (i.e. non-human readable)?
If so, then no conversion required.  An integer is already a sequence of raw bytes.

Edit: TL;DR;DU
For anyone too even be able to have a stab at helping you, you need to say how...
a) The input frequency is being provided.
b) The method by which the output data is conveyed to the synth (just saying "in hex" doesn't help).
i.e. Provide the Interface, library, protocol specification used.

Callum_Austin11

Hi, thanks for the reply. Sorry if I'm using the wrong terminology, I'm still quite new.
The synthesizer is programmed using registers. For example 0x2A03E8. The 2A is the register and the 03E8 is the data, just in hex format. For the synth to actaully generate a signal its N divider needs to be changed. The N divider is the signal you want divided by the Phase detector input frequency. That being 50Mhz. So lets say you wanted the synth to output 15GHz, you would do 15,000MHz divided by 50MHz to get your N divider value, that being 300 for example. The N divider is the part you need to change in order to change the output frequency of the synth. So its all well and good the N divider being a whole number as this can be sent as a single register, however if you get a decimal point, the decimal part needs changing into a fraction, then it needs to be sent over in two registers. The first register being the numerator and the second being the denominator. I don't need to know the code of how the frequency gets inputted, I've worked that bit out. 

Here is the datasheet for the synth with its register files. Scroll down to page 51 for more details on the N divider registers.

https://www.ti.com/lit/ds/snas736c/snas736c.pdf?ts=1593548179132&ref_url=https%253A%252F%252Fwww.google.com%252F

pcbbc

It's okay, you're confused...

Then that value is not "in hex". It's just displayed in hex in the programming specification because...
...well, it has to be displayed in some human readable format (be that hex, decimal, binary, octal) for you to be able to read and understand a number on a written page.  They could equally well have written the specification in decimal, and it wouldn't have changed one iota what bytes of data you have to send the device.

Your device seems to use SPI interface. That excepts single bytes of data a byte at a time.

Put the values you need into integer/byte variables, then send the those a byte at a time via SPI. There's absolutely no need for hex/decimal/binary conversion to do this.

Callum_Austin11

So I have actually managed to program the device, however I've only been able to do one single frequency. I now want to program it so it can do every frequency it can do. I just need to find a way to split a number into two. I'm not sure what code to use though. So for example how do I go about splitting 261.03 into two numbers so that I've got 261 and 0.03. Now that's just an example and isn't a fixed value.

pcbbc

#5
Jun 30, 2020, 11:20 pm Last Edit: Jun 30, 2020, 11:23 pm by pcbbc
You have the value as a float?
Code: [Select]
float f = 261.03;
int int_part = (int)f;
int dec_part = (f - int_part) * 1000;


It's usually easier if you show some code.

TheMemberFormerlyKnownAsAWOL

Quote
Now, the user will input a desired frequency down to 0.5mhz steps. So for example 13,051.5 MHz.
Did you really mean "mHz steps ?
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

johnwasser

Looks like the multiplier has a 16-bit integer part and 32-bit numerator and denominator in the fractional part.  You could use a denominator of 4.2 billion but since an Arduino 'float' only has 6 significant digits it wouldn't gain you anything so I'm using 1,000,000.0

Code: [Select]
float frequencyMHz = 13,051.5;
const float baseOscillatorMHz = 50.0;

float multiplier = frequencyMHz / baseOscillatorMHz;  // 261.03

uint16_t integerPart = multiplier;  // This is 261

float fractionalPart = multiplier - integerPart;
uint32_t numerator = fractionalPart * 1000000.0;  // 30000
uint32_t denominator = 1000000.0;
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp
See who has no social life: https://forum.arduino.cc/index.php?action=stats :)

Callum_Austin11

johnwasser, thank you sir.
That code really helped.
I now have a new problem.
So the data must be sent as HEX to the synthesizer. It doesn't like it being sent as a decimal or in binary. Therefore the decimal needs to be converted to HEX. However, for example, if I wanted to send 1000 in HEX format, which is 3E8 in HEX it must be sent like 0x03, 0xE8. Any idea as to how I would go about doing this?
Many thanks

pcbbc

So the data must be sent as HEX to the synthesizer. It doesn't like it being sent as a decimal or in binary. Therefore the decimal needs to be converted to HEX. However, for example, if I wanted to send 1000 in HEX format, which is 3E8 in HEX it must be sent like 0x03, 0xE8. Any idea as to how I would go about doing this?
Many thanks
Nope.  You're still confused.

A number in an integer is neither hex, decimal or binary.  It's a sequence of bytes.

0x03, 0xE8 is one possible representation of that sequence of bytes in hex.
3, 232 is another representation in decimal.
0b00000011, 0b11101000 is binary.

Doesn't change one iota the sequence of bytes you need to send.  You're just sending a sequence of bytes, there's no "coverted to HEX" about it.

You need to use the SPI library.  The SPI programming details are in section "7.5 Programming" of the datasheet.

You need to send an address and then 16 bits of data, as per the table "7.6 Register Maps".

So for example to write 0x03 0xE8 to R0...
Code: [Select]
#include <SPI.h>
SPI.begin();
...
// Write register
SPI.transfer(0x00); //R0 address, B7:0=WRITE
SPI.transfer(0x03); //Send data bits 15-8
SPI.transfer(0xE8); //Send data bits 7-0
...
// Read register
SPI.transfer(0x80); //R0 address, B7:1=READ
uint8_t hi = SPI.transfer(0x00); //Read data bits 15-8
uint8_t lo = SPI.transfer(0x00); //Read data bits 7-0

That's the basics.  You'll need to decide which registers to read and write according to the datasheet.  I just picked R0 as an example (it's not correct).  I could also have the bytes round the wrong way (0xE8 first, 0x03 second), it wasn't immediately apparent to me which way around they are sent.


Callum_Austin11

Yes, I've actually managed to do what you've said, as in sending the data over, However, after doing the maths to work out what the N divider is and so on, this is in decimal format. That then needs to be converted into HEX using code in arduino to be sent over to the synth. However it doesn't like being sent the information 0xFFFF, it needs to be split into two, 0xFF and 0xFF

gfvalvo

#11
Jul 01, 2020, 02:08 pm Last Edit: Jul 01, 2020, 02:09 pm by gfvalvo
That then needs to be converted into HEX using code in arduino to be sent over to the synth.
It constantly amazes me how people get wrapped around the axle with this. The device does not need the data to be sent as "Hex". The data is transferred in binary -- which is the only way that data can be sent over a SPI interface. This is fully explained in Sections 6.6, 7.5, and 7.6 of the datasheet.

As has been stated in this thread (multiple times), "Hex" is simply a human-readable representation of the binary data. It's convenient because an 8-bit byte can be represented as 2 "Hex" digits. That's all it is. If the data were truly required in "Hex", then you'd have to send 2 ASCII bytes (in binary) for each byte of required binary data. That would be ridiculously inefficient.

So, please, stop obsessing about "Hex", read the datasheet, and learn how to transfer binary data over a SPI interface.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

pcbbc

Yes, I've actually managed to do what you've said, as in sending the data over, However, after doing the maths to work out what the N divider is and so on, this is in decimal format. That then needs to be converted into HEX using code in arduino to be sent over to the synth. However it doesn't like being sent the information 0xFFFF, it needs to be split into two, 0xFF and 0xFF
Nope.  Still no "conversion to HEX in the Arduino".  You've split the number into high and low bytes, that's all.  Those bytes are no more in hex than they are in binary or decimal (unless of course you are writing them down).

Code: [Select]
uint16_t divider = 1000;
uint8_t divider_hi = (uint8_t)(divider >> 8);
uint8_t divider_lo = (uint8_t)divider;


You are of course right that you cannot fit a 16-bit value into an 8 bit bit, and so you need to split the 16-bit value into two 8-bit bytes.  That still does not require any "conversion to hex" for the Arduino.

The way you covert it using pen and paper (or a calculator) may be converting it to hex.  Or you could do...
1000 / 256 = 3 remainder 232.
Doesn't mean that is what the Arduino is doing.

Number format (hex, decimal, binary) is something you impose on a number when you format it for display.  The data bytes you send over SPI is NOT being used for display.

pcbbc

The data is transferred in binary
...I'd prefer to say it's transferred as a stream of bits (or as a single octet).

If "in hex" means a sequence of ASCII characters '0'..'9', 'A'..'F', and "in decimal" means a sequence of ASCII characters '0'..'9', then by logical extension "in binary" should mean a sequence of ASCII characters '0' or '1'.

gfvalvo

#14
Jul 01, 2020, 02:41 pm Last Edit: Jul 01, 2020, 02:48 pm by gfvalvo
.... then by logical extension "in binary" should mean a sequence of ASCII characters '0' or '1'.
As an exact parallel, I suppose that's true. However, "in binary" is generally understood to be "bits on the wire" by people who know what they're talking about (since only a lunatic would transfer 8 ASCII 1s or 0s for every byte being sent).

On the other hand, you could "send Hex" by using 16QAM.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

Go Up