# Is this code too much of a bodge?

#### Diver300

##### Well-Known Member
I need to work out a divide ratio on a PIC for a baud rate. The number put into the PIC's baud rate generator is 6 bits, and is one less than the divide ratio.

With a baud rate of 1000, there is no divide, so a ratio of 1, and an input number of 0.
The only other baud rates that I need are 500, 250 and 125, with divides of 2, 4 and 8 so the number to be put into the register is 1, 3, or 7 for those baud rates.

If the baud rate isn't one of those, I don't want the code to crash or to try to put numbers outside the 6 bits, but I don't care what the divide ratio ends up as.

The code that I've got is:-
Code:
    mov        baud_rate, w0
ff1r       w0, w0                ;this finds which bit is the first 1 from the right, so 125 gives 1, 250 gives 2, 500 gives 3 and 1000 gives 4
mov        #0b1110, w1
lsr        w1, w0, w0            ; 0b1110 is shifted right by 1, 2, 3 or 4 to give 7, 3, 1 or 0
mov        w0, BRG               ; Move the answer into the baud rate generator
Now that is obviously quite short, runs quickly, and does what I want for the defined baud rates.

The issue is that for other starting numbers, the divide ratio would far from the nearest value. If I want a different baud rate divide, I can't just enter the right value. For example, if I put in a baud rate of 200, this code will give a value of 0 and a baud rate of 1000, where something more complicated could be written that would give the correct value of 4, so a divide of 5.

However, there are lots of other baud rates, like 800, which can't be done with the simple divide, and would need other parts of the code modifying if I were to ever allow for number like that.

So is it unwise to put in code like this, that isn't really looking at the value being sent to it, but instead is relying on a bit of a quirk of the numbers?

#### Nigel Goodwin

##### Super Moderator
My main thought is 'why calculate the BRG value' at all?, you normally do that before hand, and simply insert the value in your source code - or as often as not, simply read the value off the datasheet, they usually have alist of the most common settings. Or, there are a number of baudrate setting generator programs online which you can use to do it for you.

#### Diver300

##### Well-Known Member
The actual baud-rate can be set by the user, which won't always be me.

The devices have lots and lots of user-configurable options. Baud rate will be one more of the options. There will be a pull-down list of options for the baud rate, just like on many terminal emulators.

#### Nigel Goodwin

##### Super Moderator
The actual baud-rate can be set by the user, which won't always be me.

The devices have lots and lots of user-configurable options. Baud rate will be one more of the options. There will be a pull-down list of options for the baud rate, just like on many terminal emulators.
Yes, but you don't calculate the BRG values in the program, you simply choose them from a list - in assembler, probably a lookup table.

#### Diver300

##### Well-Known Member
Yes, but you don't calculate the BRG values in the program, you simply choose them from a list - in assembler, probably a lookup table.
Well it boils down to having four possible values for baud rate, 125, 250, 500 or 1000, and they need divide settings of 7, 3, 1 and 0. It's also a good idea to make sure that the divide setting is the range 0 - 63 for any value of baud rate.

The code for a look up table would presumably divide (or shift) before to get the length of the table small, but it would be be a lot longer than the five lines of code in my first post.

The question I had was whether it better to have a look up table that is looking at the most significant bits of the baud rate, rather than my code that looks at the least significant bits.

#### Nigel Goodwin

##### Super Moderator
Well it boils down to having four possible values for baud rate, 125, 250, 500 or 1000, and they need divide settings of 7, 3, 1 and 0. It's also a good idea to make sure that the divide setting is the range 0 - 63 for any value of baud rate.

The code for a look up table would presumably divide (or shift) before to get the length of the table small, but it would be be a lot longer than the five lines of code in my first post.

The question I had was whether it better to have a look up table that is looking at the most significant bits of the baud rate, rather than my code that looks at the least significant bits.
I don't think anyone else has ever considered calculating the settings rather than having a lookup table?. What PIC are you using?, as it seems an unusually 'easy' calculation, and why are you using non-standard baud rates?. From your code sample, I presume there's nothing else that you need to set as well?

#### Diver300

##### Well-Known Member
It's a p24HJ64GP504 and the baud rate is for the CANbus. The full calculation from oscillator frequency is really complicated, and I'm not getting the PIC to perform that calculation. The other values have been worked out on paper / spreadsheet / computer and are hard-coded into the PIC, so the code is really simple and I haven't included it. There are loads and loads of settings for the CAN module. In this case, the CAN IDs and the data position within the CAN frame will be configurable by the user as well.

The CAN module has a divider that divides by 1 to 64, and I have arranged all the other values so that divide by 1 gives 1000 kbaud, a fairly common CANbus baud rate. Dividing by 2, 4 or 8 gives 500 kbaud, 250 kbaud and 125 kbaud. Those 4 cover all the data rates that I want at the moment.

The simple divide could get me other rates that are integer divides of 1000, like 200 kbaud or 25 kbaud. If I wanted any other rates, like 800 kbaud or 300 kbaud, various other values would have to be changed. I'm fairly sure that I wouldn't try any sort of calculation on a PIC for those.