FM Tuner TEA5767 selecting Frequency

tim griff

Member
DearAll

With a bit of time on my hands I want to built a waterproof radio because a lot of time is spent outdoors.

I have a TEA 5767 module , which with the help of another member's code from this forum I can receive stations.

However the station frequency is entered into the module via the programming cable and are set as constants.

Can anyone help me work out how to enter variables (b0 = 93 b1= 3) which will be stored in memory into the the formula. I hope I'm not stepping into 32bit maths territory!

thanks

Stay Safe

Tim




#picaxe 20m2
#no_data
#terminal 4800

hi2csetup i2cmaster, %11000000, i2cfast, i2cbyte ;tea5767

pause 3000

;(4*(93.3*1000000+225000))/32768


Symbol freq = 93300000 ; 93.3 MHz
Symbol freqValue = freq + 225000 ;for HSI
Symbol freqVal = freqValue / 8192
Symbol freqVal.msb = freqVal / 256
Symbol freqVal.lsb = freqVal & 255




pause 100
rem sertxd ("Start",13,10)
main:
rem sertxd (freqSmall,13,10) ; was "#frqsmall"
hi2cout 0,(freqVal.msb,freqVal.lsb,$10,$10,$40)
rem gosub serOutTunerData
goto main

serOutTunerData:
pause 1000
hi2cin 0,(b0,b1,b2,b3,b4)
sertxd ("Byte1: ",bit7,bit6,bit5,bit4,bit3,bit2,bit1,bit0,13,10)
sertxd ("Byte2: ",bit15,bit14,bit13,bit12,bit11,bit10,bit9,bit8,13,10)
sertxd ("Byte3: ",bit23,bit22,bit21,bit20,bit19,bit18,bit17,bit16,13,10)
sertxd ("Byte4: ",bit31,bit30,bit29,bit28,bit27,bit26,bit25,bit24,13,10,13,10)
pause 9000
return
 

AllyCat

Senior Member
Hi,
; (4*(93.3*1000000+225000))/32768
If that's the formula you want to solve, then perhaps I can help:

First, redistribute those rows of zeros, e.g. to : 4000 * (933 * 100 + 225 ) / 32768

Next, 32768 is exactly half of 65536 (216) which is used as an additional divisor by the ** multiplication operator. So multiply the "top" and "bottom" by 2 to give the formula :
8000 * ( 93300 + 225 ) / 65536

93300 is still too large to fit into 16 bits (and 8000 * 10 also would be) so multiply the 8000 by (e.g.) 5 and to compensate, divide the part in the brackets by 5. So we get:

40000 * ( 18660 + 45 ) / 65536 which you can do directly in PICaxe Basic with : 18660 + 45 ** 40000 to give a result which fits within a 16-bit word value , i.e. 11416. Strictly, that could be rounded up to 11417, which would be checked by also using the normal * operator (and seeing that this result is > 32767) or to give the full "fractional binary" part of the result (41024, I believe).

Is that the result you wanted?

Cheers, Alan.
 

tim griff

Member
Hi Alan,

YES

I barely understood my question never mind your answer!!!!!!

Brilliant , The bytes contain the values in the line of code ie 152 and 44. These are sent out via I2C.

I just need to check the solution covers all of the FM broadcast range (87 - 108 MHZ)
(93.3MHZ is Radio 4 in Shropshire)

Kindest regards
Tim
 

hippy

Technical Support
Staff member
I did it slightly differently, but it took a lot of brain ache.

If we assume that 'w2' will contain a number representing the frequency we want so 875 represents 87.5 MHz and 1080 represents 108.0 MHz ...

FMHz = w2 * 100000

Then for the 'N' number programmed into the chip ...

N = 4 * ( FMHz + 225000 ) / 32768

N = 4 * ( ( w2 * 100000 ) + 225000 ) / 32768

N = 2 * ( ( w2 * 100000 ) + 225000 ) / 16384

N = ( ( w2 * 100000 ) + 225000 ) / 8192

N = ( ( w2 * 50000 ) + 112500 ) / 4096

N = ( ( w2 * 50000 ) + 65536 + 46964 ) / 4096

And, noting that the result is always less than 65536, that can be implemented rather simply as below ...
Code:
Test:
  b0 =  87 : b1 = 5 : Gosub Convert ;  87.5 MHz
  b0 =  93 : b1 = 3 : Gosub Convert ;  93.3 MHz
  b0 = 100 : b1 = 0 : Gosub Convert ; 100.0 MHz
  b0 = 108 : b1 = 0 : Gosub Convert ; 108.0 MHz
  End

Convert:
  SerTxd( #b0, ".", #b1, " MHz", TAB, "=> " )

  w2 = b0 * 10 + b1
  w1 = w2 ** 50000 + 1 * 16
  w0 = w2 *  50000
  w2 = w0
  w0 = w0 + 46964
  If w0 < w2 Then
    w1 = w1 + 16
  End If
  w0 = w0 / 4096 + w1
  w1 = 0

  SerTxd( #w0, CR, LF )
  Return
Code:
87.5 MHz    => 10708
93.3 MHz    => 11416
100.0 MHz   => 12234
108.0 MHz   => 13211
That matches the datasheet example for 100 MHz. Also confirms your result for 93.3 MHz.

The check for w0 overflow ...
Code:
  w0 = w2 *  50000
  w2 = w0
  w0 = w0 + 46964
  If w0 < w2 Then
Can be optimised as below, but my brain is so frazzled that I can't figure if XXXXX should be 65536-46964 or 65535-46964 or something else ...
Code:
  w0 = w2 *  50000 + 46964
  If w0 < XXXXX Then
 

hippy

Technical Support
Staff member
Belatedly, checking for overflow ...

w0 + 46964 >= 65536

w0 >= 65536 - 46964

w0 >= 18572

So applying successive optimisations ...
Code:
  w1 = b0 * 10 + b1 ** 50000 + 1 * 16
  w0 = b0 * 10 + b1 *  50000 + 46964
  If w0 >= 18572  Then
    w1 = w1 + 16
  End If
  w0 = w0 / 4096 + w1
  w1 = 0
Code:
  w1 = b0 * 10 + b1 ** 50000 + 1 * 16
  w0 = b0 * 10 + b1 *  50000 + 46964
  w1 = w0 / 18752 Max 1 * 16 + w1
  w0 = w0 / 4096 + w1
  w1 = 0
Code:
  w1 = b0 * 10 + b1 ** 50000 + 1
  w0 = b0 * 10 + b1 *  50000 + 46964
  w1 = w0 / 18752 Max 1 + w1 * 16
  w0 = w0 / 4096 + w1
  w1 = 0
 
Last edited:

tim griff

Member
Hi Hippy,

Thanks - I bet this made you head hurt!!!!!

It works a treat. I don't fully understand all of it yet, i'll work my way through it.

Thanks again

Tim
 
Top