News:

Let's find out together what makes a PIC Tick!

Main Menu

Off topic enjoyable project

Started by top204, Aug 12, 2022, 11:05 AM

Previous topic - Next topic

top204

Below is an image I scanned from a 1937 magazine "Popular Wireless". I put it in photoshop and tidied it a bit, and isn't it lovely?

At that time (1937), my lovely dad would have been 5 years old, watching his dad messing around with wireless sets on the kitchen table. Then when dad's little boy was old enough to talk (me), he taught him to love electronics as well. So, to me, it has meaning. :-) And I still love electronics, but not so much the new stuff which does not have enough meaning anymore. But give me an old valve wireless or TV or old transistor radio with germanium transistors to repair, and I am in a world of my own. I was born in the wrong era. LOL

I'm going to use the image for my SI4730 chip radio project on my web site. :-)

The project uses an SI4730 chip and an inexpensive Alphanumeric LCD, and an inexpensive Rotary Encoder for the menu system and tuning. The menu system changes bands and allows some of the radio chip's registers to be manipulated for antenna cap and AGC etc... It covers MW, SW and FM. All with 3 chips. i.e. A PIC18F microcontroller, an SI4730 chip and a TDA2822 chip for an audio amplifier. All written in Positron8, and written so it can clearly be seen what the code is doing, and why it is doing it.

1930s Man with Radio - Small Cartoon Image.jpg






John Drew

G'day Les,
Seems a fun project Les.
I know you don't have a signal generator but do you have a feeling for the sensitivity?

Like you, my Dad cultivated my interest in technology and mechanics from an early age. We weren't a rich family in terms of money but very rich in terms of family love and cultivation of our minds. Dad's home workshop was a boon too. Many stories could be told.

Unfortunately society seems to be heading down different paths where children are lower in the priorities for some. As a school principal I saw the difference caring parents make.

Best wishes from Oz,
John

top204

#2
Lovely words John.

I was also brought up in a family full of love, but not much money, because my dad was a bricklayer for the local council. But as soon as they had re-built the country after the war, they were dumped on and wages stagnated from the 1960s onwards for the council workers. :-( So nothing has actually changed with the wealthy controlling the normal, hard working, people that make them wealthy in the first place. :-) I'm not political, but the torys (conservative politicians controlling this country for the past 43 years) have there dream come true... Nearly back to the victorian age and mentality here in the UK, with the rich controlling the poor and people starving and freezing to death, while the wealthy politicians and civil servant chiefs and sponging business people live it up a few miles away from it all.

My dad, just like your dad seemed to be, was a very intelligent man, and I still remember asking him as a boy: "why didn't you go into electronics as a job?" His words were: "I didn't go to grammar school, so I didn't have that little bit of paper to say I could do it". So again, nothing has changed, and actually gotten worse over time. My granda (dad's dad) was a riveter/plater in the shipyards, but was also intelligent and was messing with electronics when it first came into being back in the early 20th century onwards, and his interest rubbed off on dad. Dad was the baby of his large, loving, family, and nanna and granda were in their mid-forties when he was born. :-) Nanna Johnson, sadly, passed away when I was only 6 months old and granda when I was only 7 years old, but I have always been a curious person, so as I was growing up, I used to ask dad lots and lots of questions about them and him as a boy, and dad loved talking about his boyhood and his mum and dad. So the stories and facts stuck in my memory because they were so important to me. Heck.... I even look like my granda Johnson and my dad. :-)

Anyway...... I have the radio working on a solderless breadboard, and even with an aeriel a couple of feet in length, I was picking up some Asian radio channels on SW, and the odd radio HAM, but HAMs are becoming fewer and far between as well. The MW is clear, but not a lot of channels on MW anymore, and the VHF FM is rock solid, but again, not a lot on it anymore.

charliecoutas

Les, John

The project sounds wonderful Les, I'll make/buy one. My interest in electronics came from an old guy who lived opposite, when I was around 8. I'm afraid there was no encouragement from my Dad, he would occasionally remind me that my school report always said: "Doing OK but could do better".

I've got the Space Invaders going, it's great and I am modding it for Escape Room use. Thanks to Bob who kindly donated a graphic display.

Yes, the World is changing: I watch the faces of schoolkids when they visit the museum and I don't see many showing an actual interest in the wonderful old valve equipment we have on display, some of it running. I'm not sure who's going look after the gear after the old geezers (me included) who look after it finally hang up their soldering irons and move off this mortal coil.

Keep it up Les, you are doing a very worthwhile thing.

Charlie


top204

#4
Many thanks Charlie.

I am still looking forward, very much, to visiting Bletchley when we finally move home. If it ever happens, because house prices are still going up in North Norfolk/South Lincolnshire for some inexplicable reason! And they are now going out of our price range. :-(

Just as a teaser. I have listed the SI4730 library code below. It is the pre-release version, and the extra features of the chip are still under test on my breadboard. The AM mode goes from about 500KHz to about 23MHz. The FM mode goes from about 60MHz to about 110MHz (apparently, but not tested for those frequencies yet).

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' A set of procedures to interface with a Silicon Labs Si4730 radio device
'
' Written by Les Johnson for the Positron8 BASIC compiler.
'
$define Si47_cADDR_SEN_LOW  $11                         ' Si473X I2C bus address when the SEN pin is set to low 0V
$define Si47_cADDR_SEN_HIGH $63                         ' Si473X I2C bus address when the SEN pin is set to high +3.3V

$define cFM_MODE    0b00010000                          ' FM using an external 32KHz crystal oscillator
$define cAM_MODE    0b00010001                          ' AM using an external 32KHz crystal oscillator, and SSB (if patch applied)
$define cWB_MODE    0b00000011                          ' Weather Band Receiver
$define cPATCH_MODE 0b00001111
'
' Si473X commands (general)
'
$define cCMD_POWER_UP       $01                         ' Power up the device and mode selection
$define cCMD_GET_REV        $10                         ' Returns revision information on the device
$define cCMD_POWER_DOWN     $11                         ' Power down the device
$define cCMD_SET_PROPERTY   $12                         ' Sets the value of a property
$define cCMD_GET_PROPERTY   $13                         ' Retrieves a property's value
$define cCMD_GET_INT_STATUS $14                         ' Read interrupt status bits
'
' FM
'
$define cFM_TUNE_FREQ    $20
$define cFM_SEEK_START   $21                            ' Begins searching for a valid FM frequency
$define cFM_TUNE_STATUS  $22
$define cFM_AGC_STATUS   $27
$define cFM_AGC_OVERRIDE $28
$define cFM_RSQ_STATUS   $23
$define cFM_RDS_STATUS   $24                            ' Returns RDS information for current channel and reads an entry from the RDS FIFO
'
' FM RDS properties
'
$define cFM_RDS_INT_SOURCE     $1500
$define cFM_RDS_INT_FIFO_COUNT $1501
$define cFM_RDS_CONFIG         $1502
$define cFM_RDS_CONFIDENCE     $1503

$define cFM_DEEMPHASIS                       $1100
$define cFM_BLEND_STEREO_THRESHOLD           $1105
$define cFM_BLEND_MONO_THRESHOLD             $1106
$define cFM_BLEND_RSSI_STEREO_THRESHOLD      $1800
$define cFM_BLEND_RSSI_MONO_THRESHOLD        $1801
$define cFM_BLEND_SNR_STEREO_THRESHOLD       $1804
$define cFM_BLEND_SNR_MONO_THRESHOLD         $1805
$define cFM_BLEND_MULTIPATH_STEREO_THRESHOLD $1808
$define cFM_BLEND_MULTIPATH_MONO_THRESHOLD   $1809
$define cFM_CHANNEL_FILTER                   $1102
'
' FM Seek Properties
'
$define cFM_SEEK_BAND_BOTTOM         $1400              ' Sets the bottom of the FM band for seek
$define cFM_SEEK_BAND_TOP            $1401              ' Sets the top of the FM band for seek
$define cFM_SEEK_FREQ_SPACING        $1402              ' Selects frequency spacing for FM seek
$define cFM_SEEK_TUNE_SNR_THRESHOLD  $1403              ' Sets the SNR threshold for a valid FM Seek/Tune
$define cFM_SEEK_TUNE_RSSI_THRESHOLD $1404              ' Sets the RSSI threshold for a valid FM Seek/Tune
'
' NBFM Commands
'
$define cNBFM_TUNE_FREQ    $50
$define cNBFM_TUNE_STATUS  $52
$define cNBFM_RSQ_STATUS   $53
$define cNBFM_AGC_STATUS   $57
$define cNBFM_AGC_OVERRIDE $58
'
' NBFM Properties
'
$define cAM_MAX_TUNE_ERROR          $5108
$define cNBFM_RSQ_INT_SOURCE        $5200
$define cNBFM_RSQ_SNR_HI_THRESHOLD  $5201
$define cNBFM_RSQ_SNR_LO_THRESHOLD  $5202
$define cNBFM_RSQ_RSSI_HI_THRESHOLD $5203
$define cNBFM_RSQ_RSSI_LO_THRESHOLD $5204
$define cNBFM_VALID_SNR_THRESHOLD   $5403
$define cNBFM_VALID_RSSI_THRESHOLD  $5404
'
' AM commands
'
$define cAM_TUNE_FREQ    $40                            ' Tunes to a given AM frequency
$define cAM_SEEK_START   $41                            ' Begins searching for a valid AM frequency
$define cAM_TUNE_STATUS  $42                            ' Queries the status of the already issued cAM_TUNE_FREQ or cAM_SEEK_START command
$define cAM_RSQ_STATUS   $43                            ' Queries the status of the Received Signal Quality (RSQ) for the Current channel
$define cAM_AGC_STATUS   $47                            ' Queries the Current AGC settings
$define cAM_AGC_OVERRIDE $48                            ' Overrides AGC settings by disabling and forcing it to a fixed value
$define cCMD_GPIO_CTL    $80                            ' Configures GPO1, 2, and 3 as output or Hi-Z
$define cCMD_GPIO_SET    $81                            ' Sets GPO1, 2, and 3 output level (low or high)
'
' SSB command (SAME AM CMD VALUES)
' See AN332 Rev 0.8 Universal Programming Guide, pages 4 and 5
'
$define cSSB_TUNE_FREQ    $40                           ' Tunes to a given SSB frequency
$define cSSB_TUNE_STATUS  $42                           ' Queries the status of the already issued cSSB_TUNE_FREQ or cAM_SEEK_START command
$define cSSB_RSQ_STATUS   $43                           ' Queries the status of the Received Signal Quality (RSQ) for the Current channel
$define cSSB_AGC_STATUS   $47                           ' Queries the Current AGC settings
$define cSSB_AGC_OVERRIDE $48                           ' Overrides AGC settings by disabling and forcing it to a fixed value
'
' AM/SW/LW Receiver Property Summary
'
$define cDIGITAL_OUTPUT_FORMAT                $0102     ' Configure digital audio outputs
$define cDIGITAL_OUTPUT_SAMPLE_RATE           $0104     ' Configure digital audio output sample rate
$define cREFCLK_FREQ                          $0201     ' Sets frequency of reference clock in Hz. The range is 31130 to 34406 Hz, or 0 to disable the AFC. Default is 32768 Hz
$define cREFCLK_PRESCALE                      $0202     ' Sets the prescaler value for RCLK input
$define cAM_DEEMPHASIS                        $3100     ' Sets deemphasis time constant. De-emphasis is disabled by default
$define cAM_CHANNEL_FILTER                    $3102     ' Selects the bandwidth of the channel filter for AM reception. The choices are 6, 4, 3, 2, 2.5, 1.8, or 1 (KHz). The default bandwidth is 2 KHz
$define cAM_AUTOMATIC_VOLUME_CONTROL_MAX_GAIN $3103     ' Sets the maximum gain for automatic volume control
$define cAM_MODE_AFC_SW_PULL_IN_RANGE         $3104     ' Sets the SW AFC pull-in range
$define cAM_MODE_AFC_SW_LOCK_IN_RANGE         $3105     ' Sets the SW AFC lock-in
$define cAM_RSQ_INTERRUPTS                    $3200     ' Same SSB - Configures interrupt related to Received Signal Quality metrics. All interrupts are disabled by default
$define cAM_RSQ_SNR_HIGH_THRESHOLD            $3201     ' Sets high threshold for SNR interrupt
$define cAM_RSQ_SNR_LOW_THRESHOLD             $3202     ' Sets low threshold for SNR interrupt
$define cAM_RSQ_RSSI_HIGH_THRESHOLD           $3203     ' Sets high threshold for RSSI interrupt
$define cAM_RSQ_RSSI_LOW_THRESHOLD            $3204     ' Sets low threshold for RSSI interrupt
$define cAM_SOFT_MUTE_RATE                    $3300     ' Sets the attack and decay rates when entering or leaving soft mute. The default is 278 dB/s
$define cAM_SOFT_MUTE_SLOPE                   $3301     ' Sets the AM soft mute slope. Default value is a slope of 1
$define cAM_SOFT_MUTE_MAX_ATTENUATION         $3302     ' Sets maximum attenuation during soft mute (dB). Set to 0 to disable soft mute. Default is 8 dB
$define cAM_SOFT_MUTE_SNR_THRESHOLD           $3303     ' Sets SNR threshold to engage soft mute. Default is 8 dB
$define cAM_SOFT_MUTE_RELEASE_RATE            $3304     ' Sets softmute release rate. Smaller values provide slower release, and larger values provide faster release
$define cAM_SOFT_MUTE_ATTACK_RATE             $3305     ' Sets software attack rate. Smaller values provide slower attack, and larger values provide faster attack
$define cAM_SEEK_BAND_BOTTOM                  $3400     ' Sets the Bottom of the AM band for seek. Default is 520
$define cAM_SEEK_BAND_TOP                     $3401     ' Sets the Top of the AM band for seek. Default is 1710
$define cAM_SEEK_FREQ_SPACING                 $3402     ' Selects frequency pSpacing for AM seek. Default is 10 KHz pSpacing
$define cAM_SEEK_SNR_THRESHOLD                $3403     ' Sets the SNR threshold for a valid AM Seek/Tune
$define cAM_SEEK_RSSI_THRESHOLD               $3404     ' Sets the RSSI threshold for a valid AM Seek/Tune
$define cAM_AGC_ATTACK_RATE                   $3702     ' Sets the number of milliseconds the high peak detector must be exceeded before decreasing gain
$define cAM_AGC_RELEASE_RATE                  $3703     ' Sets the number of milliseconds the low peak detector must not be exceeded before increasing the gain
$define cAM_FRONTEND_AGC_CONTROL              $3705     ' Adjusts AM AGC for front end (external) attenuator and LNA
$define cAM_NB_DETECT_THRESHOLD               $3900     ' Sets the threshold for detecting impulses in dB above the noise floor
$define cAM_NB_INTERVAL                       $3901     ' Interval in micro-seconds that original samples are replaced by interpolated clean samples
$define cAM_NB_RATE                           $3902     ' Noise blanking rate in 100 Hz units. Default value is 64
$define cAM_NB_IIR_FILTER                     $3903     ' Sets the bandwidth of the noise floor estimator. Default value is 300
$define cAM_NB_DELAY                          $3904     ' Delay in micro-seconds before applying impulse blanking to the original samples

$define cRX_VOLUME    $4000
$define cRX_HARD_MUTE $4001
'
' Parameters
'
$define cRDS_OUTPUT_ONLY        0b00000000          ' RDS output only (no audio outputs) Si4749 only
$define cANALOGUE_AUDIO         0b00000101          ' Analogue Audio Outputs
$define cDIGITAL_AUDIO1         0b00001011          ' Digital audio output (DCLK, LOUT/DFS, ROUT/DIO)
$define cDIGITAL_AUDIO2         0b10110000          ' Digital audio outputs (DCLK, DFS, DIO)
$define cANALOGUE_DIGITAL_AUDIO 0b10110101          ' Analogue and digital audio outputs (LOUT/ROUT and DCLK, DFS, DIO)
'
' Other parameters
'
$define cFM_CURRENT_MODE   0
$define cAM_CURRENT_MODE   1
$define cSSB_CURRENT_MODE  2
$define cNBFM_CURRENT_MODE 3

$define cSEEK_UP   1
$define cSEEK_DOWN 0

$define cDelay_After_Set_Frequency 30               ' In ms - This value helps to improve the precision during the reading of the frequency value
$define cDelay_After_PowerUp       10               ' In ms - Max delay you have to setup after a power up command
$define cDelay_WaitToSend          300              ' In uS (Microsecond) - Each loop of waitToSend sould wait this value in microsecond
$define cSeek_Time                 8000             ' Defines the maximum seeking time. 8 seconds is the default

$define cXOSCEN_CRYSTAL 1                           ' Use the crystal oscillator
$define cXOSCEN_RCLK    0                           ' Use an external RCLK (crystal oscillator is disabled)
'
' Response Status bits
'
$define cCTS    7
$define cERR    6
$define cRDSINT 2
$define cASQINT 1
$define cSTCINT 0
'
' Set AM or FM mode
'
$define Si47_cMode_AM 0
$define Si47_cMode_FM 1
'
' AM Channel Filter values
'
$define Si47_cChanFilter_6000Hz 0
$define Si47_cChanFilter_4000Hz 1
$define Si47_cChanFilter_3000Hz 2
$define Si47_cChanFilter_2000Hz 3
$define Si47_cChanFilter_1000Hz 4
$define Si47_cChanFilter_1800Hz 5
$define Si47_cChanFilter_2500Hz 6

$define True 1
$define False 0
'
    Symbol Si47_cAddr = (Si47_cADDR_SEN_LOW << 1)           ' Set the address of the device with its SEN pin grounded
'
' Create some variables for the library
'
    Dim Si47_dParamTemp  As Dword Access
    Dim Si47_wParamTemp1 As Si47_dParamTemp.Word0
    Dim Si47_wParamTemp2 As Si47_dParamTemp.Word1
    Dim Si47_bParamTemp1 As Si47_dParamTemp.Byte0
    Dim Si47_bParamTemp2 As Si47_dParamTemp.Byte1

    Dim Si47_wTimeout As Word                               ' Holds the timeout counter for the read procedures
    Dim Si47_bStatus  As Byte                               ' Holds the status return value from the Si473X device
    Dim Si47_bVolume  As Byte                               ' Holds the audio volume value
    Dim Si47_wFrequency As Word                             ' Holds the frequency sent to the device
    Dim Si47_wAntCap  As Word                               ' Holds the Antenna Capacitor sent to the device
    Dim Si47_bMode    As Byte                               ' Holds the mode that the device is in: AM, FM or WB

    Dim Si47_bRespBuffer[10] As Byte                        ' Holds the response values read from the device
    Dim Si47_bResponse1H As Si47_bRespBuffer#1              ' \
    Dim Si47_bResponse1  As Si47_bRespBuffer#2              ' | Bytes are reversed because the frequency is read high byte first
    Dim Si47_wResponse1  As Si47_bResponse1.Word            ' /

    Dim Si47_bResponse2  As Si47_bRespBuffer#3
    Dim Si47_bResponse2H As Si47_bRespBuffer#4
    Dim Si47_wResponse2  As Si47_bResponse2.Word

    Dim Si47_bResponse3H As Si47_bRespBuffer#5              ' \
    Dim Si47_bResponse3  As Si47_bRespBuffer#6              ' | Bytes are reversed because the Antenna Capacitor is read high byte first
    Dim Si47_wResponse3  As Si47_bResponse3.Word            ' /
'
' Alias some response buffer elements
'
    Dim Si47_bRespStatus As Si47_bRespBuffer#0              ' Holds the status value from the response
    Dim Si47_wRespFreq   As Si47_wResponse1                 ' Holds the frequency that the device has locked onto
    Dim Si47_bRespRSSI   As Si47_bRespBuffer#3              ' Holds the RSSI of the received signal
    Dim Si47_bRespSNR    As Si47_bRespBuffer#4              ' Holds the SNR of the received signal
    Dim Si47_bRespMULT   As Si47_bRespBuffer#5
    Dim Si47_wRespAntCap As Si47_wResponse3                 ' Holds the internal Antenna Capacitor the device is using

'-------------------------------------------------------------------------------
' Write a byte to the Si473X device using an I2C interface
' Input     : pValue holds the value to send
' Output    : None
' Notes     : None
'
Proc Si47_Write8(pValue As Si47_bParamTemp1)
    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [pValue]
EndProc

'-------------------------------------------------------------------------------
' Read a byte from the Si473X device using an I2C interface
' Input     : None
' Output    : Returns the value read from the device
' Notes     : None
'
Proc Si47_Read8(), Byte
    I2CIn Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [Result]
EndProc

'-------------------------------------------------------------------------------
' Write a command and an 8-bit value to the Si473X device using an I2C interface
' Input     : pCom holds the command to write
'           : pValue holds the value to send for the command
' Output    : None
' Notes     : None
'
Proc Si47_WriteCom8(pCom As Si47_bParamTemp1, pValue As Si47_bParamTemp2)
    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [pCom, pValue]
EndProc

'-------------------------------------------------------------------------------
' Write a command and a 16-bit value to the Si473X device using an I2C interface
' Input     : pCom holds the command to write
'           : pValue holds the value to send for the command
' Output    : None
' Notes     : The value to write is sent MSB first
'
Proc Si47_WriteCom16(pCom As Si47_bParamTemp1, pValue As Si47_wParamTemp2)
    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [pCom, pValue.Byte1, pValue.Byte0]
EndProc

'-------------------------------------------------------------------------------
' Write a command and two 16-bit values to the Si473X device using an I2C interface
' Input     : pCom holds the command to write
'           : pValue1 holds the value to send for the command
'           : pValue2 holds the value to send for the command
' Output    : None
' Notes     : The values to write are sent MSB first
'
Proc Si47_WriteCom32(pCom As Si47_bParamTemp1, pValue1 As Word, pValue2 As Word)
    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [pCom, pValue1.Byte1, pValue1.Byte0, pValue2.Byte1, pValue2.Byte0]
EndProc

'-------------------------------------------------------------------------------
' Wait for a CTS high response from the Si473X device
' Input     : pIntStat is true if the GET_INT_STATUS command is to be sent first
' Output    : Returns true if the response was received
'           : Global variable "Si47_bStatus" holds the response value
' Notes     : None
'
Proc Si47_Get_CTS_Resp(pIntStat As Bit), Bit

    If pIntStat = True Then                                             ' Is pIntStat true?
        Si47_Write8(cCMD_GET_INT_STATUS)                                ' Yes. So send the GET_INT_STATUS command
    EndIf

    Si47_wTimeout = $4000                                               ' Load the timeout counter
    Result = True                                                       ' Default to a true return
    Do                                                                  ' Create a loop
        Si47_bStatus = Si47_Read8()                                     ' Read the Si473X device
        If Si47_bStatus.cCTS = 1 Then                                   ' Is the CTS bit high?
            ExitProc                                                    ' Yes. So exit the procedure with a true result
        EndIf
        Dec Si47_wTimeout                                               ' Decrement the timeout variable
        If Si47_wTimeout = 0 Then                                       ' Has the timeout value reached 0?
            Result = False                                              ' Yes. So return a false result
            ExitProc                                                    ' Exit the procedure
        EndIf
    Loop                                                                ' Close the loop
EndProc

'-------------------------------------------------------------------------------
' Wait for a STC high response from the Si473X device
' Input     : None
' Output    : Returns true if the response was received
'           : Global variable "Si47_bStatus" holds the response value
' Notes     : None
'
Proc Si47_Get_STC_Resp(pIntStat As Bit), Bit

    If pIntStat = True Then                                             ' Is pIntStat true?
        Si47_Write8(cCMD_GET_INT_STATUS)                                ' Yes. So send the GET_INT_STATUS command
    EndIf

    Si47_wTimeout = $4000                                               ' Load the timeout counter
    Result = True                                                       ' Default to a true return
    Do                                                                  ' Create a loop
        Si47_bStatus = Si47_Read8()                                     ' Read the Si473X device
        If Si47_bStatus.cSTCINT = 1 Then                                ' Is the STC bit high?
            ExitProc                                                    ' Yes. So exit the procedure with a true result
        EndIf
        Dec Si47_wTimeout                                               ' Decrement the timeout variable
        If Si47_wTimeout = 0 Then                                       ' Has the timeout value reached 0?
            Result = False                                              ' Yes. So return a false result
            ExitProc                                                    ' Exit the procedure
        EndIf
    Loop                                                                ' Close the loop
EndProc

'-------------------------------------------------------------------------------
' Reset an Si473X device
' Input     : None
' Output    : None
' Notes     : None
'
Proc Si47_Reset()
    PinHigh Si47_RST_Pin                                                ' \
    DelayMS 100                                                         ' |
    PinClear Si47_RST_Pin                                               ' | Reset the Si473X device
    DelayMS 200                                                         ' |
    PinSet Si47_RST_Pin                                                 ' /
EndProc

'-------------------------------------------------------------------------------
' Initialise an Si473X device
' Input     : pMode powers up the device for AM or FM mode
'           : 0 = AM mode
'           : 1 = FM mode
' Output    : Returns true if the device powered up correctly
' Notes     : Resets the device using its RST pin
'
Proc Si47_Init(pMode As Si47_bMode), Bit
    Result = True
    PinHigh Si47_SDIO_Pin
    PinHigh Si47_SCLK_Pin
    Si47_Reset()                                                        ' Reset the Si473X device
    If Si47_PowerUp(pMode) = False Then                                 ' Power up the Si473X device in the mode from the parameter
        Result = False                                                  ' Return a false value if the device did not power up correctly
        ExitProc                                                        ' Exit the procedure
    EndIf
'
' Set the mode that the device will be in
'
    If pMode = Si47_cMode_FM Then                                       ' Is the device being powered up in FM mode?
        Si47_CorrectBug_FM()                                            ' Yes. So send a sequence of bytes to correct an anomaly in the device
        Si47_SetProperty(cFM_SEEK_BAND_BOTTOM, 6400)                    ' Set the lowest seek frequency to 64 MHz
        Si47_SetProperty(cFM_SEEK_BAND_TOP, 10800)                      ' Set the highest seek frequency to 108 MHz
        Si47_SetProperty(cFM_SEEK_FREQ_SPACING, 10)                     ' 10 kHz

    ElseIf pMode = Si47_cMode_AM Then                                   ' Is the device being powered up in AM mode?
        Si47_SetProperty(cAM_SEEK_BAND_BOTTOM, 520)                     ' Yes. So set the lowest seek frequency to 520 KHz
        Si47_SetProperty(cAM_SEEK_BAND_TOP, 23000)                      ' Set the highest seek frequency to 23 MHz
        Si47_SetProperty(cAM_SEEK_FREQ_SPACING, 10)
    EndIf
    Si47_SetVolume(63)                                                  ' Set the audio volume
    Si47_wAntCap = 0                                                    ' Reset the Antenna Capacitor value sent to the device (0 is automatic)
EndProc

'-------------------------------------------------------------------------------
' Power up the Si473X device in AM or FM mode
' Input     : pMode powers up the device for AM or FM mode
'           : 0 = AM mode
'           : 1 = FM mode
' Output    : Returns 0 if not powered up correctly
' Notes     : None
'
Proc Si47_PowerUp(pMode As Si47_bMode), Bit

    If pMode = Si47_cMode_AM Then                                           ' Power up in AM mode?
        I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cCMD_POWER_UP,    ' Yes. So send the Power Up command
                                                          cAM_MODE,         ' Set to AM/SW/LW Receive
                                                          cANALOGUE_AUDIO]  ' Set to analogue audio output
    ElseIf pMode = Si47_cMode_FM Then                                       ' Otherwise... Power up in FM mode?
        I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cCMD_POWER_UP,    ' Yes. So send the Power Up command
                                                          cFM_MODE,         ' Set to FM Receive
                                                          cANALOGUE_AUDIO]  ' Set to analogue audio output
    EndIf
    Result = Si47_Get_CTS_Resp(False)                                       ' Wait for the Si473X device to alter
    DelayMS cDelay_After_PowerUp                                            ' Delay the required amount of time before returning
EndProc

'-------------------------------------------------------------------------------
' Power down the Si473X device
' Input     : None
' Output    : Returns 0 if not powered down correctly
' Notes     : None
'
Proc Si47_PowerDown(), Bit
    Si47_Write8(cCMD_POWER_DOWN)                                            ' Send the Power Down command
    Result = Si47_Get_CTS_Resp(False)                                       ' Wait for the Si473X device to alter
    DelayMS 200
EndProc

'-------------------------------------------------------------------------------
' Tune an AM signal
' Input     : pFreq (Si47_wFrequency) holds the 16-bit frequency written to the device
'           : Si47_wAntCap holds the 16-bit Antenna Capacitor value to write to the device
' Output    : None
' Notes     : None
'
Proc Si47_Tune_AM(pFreq As Si47_wFrequency)
    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cAM_TUNE_FREQ,        ' Send the command to tune AM
                                                      0b00000000,           ' Write 0 for Arg1
                                                      pFreq.Byte1,          ' \ Write the 16-bit frequency value
                                                      pFreq.Byte0,          ' /
                                                      Si47_wAntCap.Byte1,   ' \ Write the 16-bit Antenna Capacitor value (0 is automatic)
                                                      Si47_wAntCap.Byte0]   ' /
    Si47_Get_CTS_Resp(False)
    DelayMS cDelay_After_Set_Frequency                                      ' Delay the required amount of time before returning
EndProc

'-------------------------------------------------------------------------------
' Read the AM tune status
' Input     : None
' Output    : Returns the status arguments in array Si47_bRespBuffer
' Notes     : None
'
Proc Si47_Get_TuneStatus_AM(), Si47_bRespBuffer
    Si47_WriteCom8(cAM_TUNE_STATUS, 0b00000000)                             ' Send the command to read the AM tune status
    I2CIn Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [Si47_bStatus,          ' \
                                                     Str Result]            ' / Read the status response values into the result array
EndProc

'-------------------------------------------------------------------------------
' Read the AM Antenna Capacitor value from the device
' Input     : None
' Output    : Returns the Antenna Capacitor written to the device.
' Notes     : None
'
$define Si47_GetAntCap_AM() Si47_wAntCap

'-------------------------------------------------------------------------------
' Alter the AM Antenna Capacitor in the device
' Input     : pAntCap (Si47_wAntCap) holds the 16-bit Antenna Capacitor value (0 to 6143)
' Output    : Returns True if the command was successful
' Notes     : None
'
Proc Si47_SetAntCap_AM(pAntCap As Si47_wAntCap), Bit
    If pAntCap.SWord < 0 Then pAntCap = 0                                   ' \ Set the limits of the Ant Cap value
    If pAntCap > 6143 Then pAntCap = 6143                                   ' /

    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cAM_TUNE_FREQ,        ' Send the command to tune AM
                                                      0b00000000,           ' Write 0 for Arg1
                                                      Si47_wFrequency.Byte1,' \ Write the frequency value
                                                      Si47_wFrequency.Byte0,' /
                                                      pAntCap.Byte1,        ' \ Write the 16-bit Antenna Capacitor value
                                                      pAntCap.Byte0]        ' /
    DelayMS cDelay_After_Set_Frequency                                      ' Delay the required amount of time
    Result = Si47_Get_CTS_Resp(False)                                       ' Wait for the Si473X device to alter
EndProc

'-------------------------------------------------------------------------------
' Alter the De-Emphasis for AM
' Input     : pEn = True to enable the 5uS de-emphasis, False to disable it
' Output    : None
' Notes     : None
'
Proc Si47_DeEmphashasis_AM(pEn As Bit)
    Si47_SetProperty(cAM_DEEMPHASIS, pEn)
EndProc

'-------------------------------------------------------------------------------
' Alter the AGC for AM
' Input     : pValue holds the value to place into the AGC registers.
' Output    : None
' Notes     : Bit-0 of pValue is the enable/disable of AGC. Bit set to 0 = enable AGC, 1 = disable AGC
'
Proc Si47_Set_AGC_AM(pValue As Word)

    Select pValue.0
        Case 0                                                              ' Is the pValue.0 0?
            pValue.0 = 1                                                    ' Yes. So disable or enable the AGC by complementing bit-0 of the value
        Case 1                                                              ' Is the pValue.0 1?
            pValue.0 = 0                                                    ' Yes. So enable or disable the AGC by complementing bit-0 of the value
    EndSelect

    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cAM_AGC_OVERRIDE,     ' Send the command
                                                      pValue.Byte1,
                                                      pValue.Byte0,
                                                      0b00000000]
    Si47_Get_CTS_Resp(False)                                                ' Wait for the Si473X device to alter
EndProc

'-------------------------------------------------------------------------------
' Alter the Channel Filter for AM
' Input     : pChFilt holds the Channel Filter value:
'               0 = 6 kHz Bandwidth
'               1 = 4 kHz Bandwidth
'               2 = 3 kHz Bandwidth
'               3 = 2 kHz Bandwidth
'               4 = 1 kHz Bandwidth
'               5 = 1.8 kHz Bandwidth
'               6 = 2.5 kHz Bandwidth, gradual roll off
'           : pFilt is True if the mains noise reject 100Hz filter is enabled, False for disabled
' Output    : None
' Notes     : None
'
Proc Si47_ChannelFilter_AM(pChFilt As Byte, pFilt As Bit)
    Dim wChFilter As Word
    wChFilter = pChFilt & 0b00000111                                         ' Filter the Channel Filter values for the first 3 bits only (0 to 7)

    wChFilter.8 = pFilt                                                     ' Enable or disable the mains noise rejection 100Hz filter
    Si47_SetProperty(cAM_CHANNEL_FILTER, wChFilter)                         ' Send the command to alter the channel filter
EndProc

'-------------------------------------------------------------------------------------------------------------------------------
' FM procedures
'-------------------------------------------------------------------------------------------------------------------------------
' Tune an FM signal
' Input     : pFreq (Si47_wFrequency) holds the 16-bit frequency written to the device
'           : Si47_wAntCap holds the 8-bit Antenna Capacitor value to write to the device
' Output    : None
' Notes     : None
'
Proc Si47_Tune_FM(pFreq As Si47_wFrequency)

    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cFM_TUNE_FREQ,        ' Send the command to tune FM
                                                      0b00000000,           ' Write 0 to Arg1
                                                      pFreq.Byte1,          ' \ Write the frequency value
                                                      pFreq.Byte0,          ' /
                                                      Si47_wAntCap.Byte0]   ' Write the 8-bit Antenna Capacitor value (0 is automatic)
    DelayMS cDelay_After_Set_Frequency                                      ' Delay the required amount of time before returning
EndProc

'-------------------------------------------------------------------------------
' Read the FM tune status
' Input     : None
' Output    : Returns the status arguments in array Si47_bRespBuffer
' Notes     : None
'
Proc Si47_GetTuneStatus_FM(), Si47_bRespBuffer
    Si47_WriteCom8(cFM_TUNE_STATUS, 0b00000000)          ' Send the command to read the FM tune status
    I2CIn Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [Si47_bStatus, Str Result]
EndProc

'-------------------------------------------------------------------------------
' Scan tuning until a station is picked up
' Input     : pUpDown holds 1 for a scan up and 0 for a scan down
' Output    : Returns true if the command was successful
' Notes     : None
'
Proc Si47_SeekTune_FM(pUpDown As Bit), Bit
    Dim bArg As Byte = 0
    bArg.3 = pUpDown

    Si47_WriteCom8(cFM_SEEK_START, bArg)
    Result = Si47_Get_CTS_Resp(False)                                       ' Wait for the Si473X device to alter
EndProc

'-------------------------------------------------------------------------------
' Read the FM Antenna Capacitor value from the device
' Input     : None
' Output    : Returns the Antenna Capacitor, previously written to the device
' Notes     : None
'
$define Si47_GetAntCap_FM() Si47_wRespAntCap

'-------------------------------------------------------------------------------
' Alter the AM Antenna Capacitor in the device
' Input     : pAntCap (Si47_wRespAntCap) holds the 16-bit Antenna Capacitor value (0 to 6143)
' Output    : Returns True if the command was successful
' Notes     : None
'
Proc Si47_SetAntCap_FM(pAntCap As Si47_wRespAntCap), Bit
    If pAntCap.SWord < 0 Then pAntCap = 0                                   ' \ Set the limits of the Ant Cap value
    If pAntCap > 255 Then pAntCap = 255                                     ' /

    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cAM_TUNE_FREQ,        ' Send the command to tune AM
                                                      0b00000000,           ' Write 0 to Arg1
                                                      Si47_wFrequency.Byte1,' \ Write the frequency value
                                                      Si47_wFrequency.Byte0,' /
                                                      pAntCap.Byte0]        ' Write the 8-bit Antenna Capacitor value
    DelayMS cDelay_After_Set_Frequency                                      ' Delay the required amount of time
    Result = Si47_Get_CTS_Resp(False)                                       ' Wait for the Si473X device to alter
EndProc

'-------------------------------------------------------------------------------
' Alter the AGC for FM
' Input     : pValue holds the value to place into the AGC registers
' Output    : None
' Notes     : Bit-0 of pValue is the enable/disable of AGC. 0 = enable AGC, 1 = disable AGC
'
Proc Si47_Set_AGC_FM(pValue As Word)

    Select pValue.0
        Case 0                                                              ' Is the pValue.0 0?
            pValue.0 = 1                                                    ' Yes. So disable the AGC
        Case 1                                                              ' Is the pValue.0 1?
            pValue.0 = 0                                                    ' Yes. So enable the AGC
    EndSelect

    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cFM_AGC_OVERRIDE,     ' Send the command
                                                      pValue.Byte1,
                                                      pValue.Byte0,
                                                      0b00000000]
    Si47_Get_CTS_Resp(False)                                                ' Wait for the Si473X device to alter
EndProc

'-------------------------------------------------------------------------------------------------------------------------------
' General purpose procedures
'-------------------------------------------------------------------------------------------------------------------------------
' Read the volume value from the device
' Input     : None
' Output    : Returns the volume value from the device
' Notes     : Also loads global variable Si47_bVolume with the volume value
'
Proc Si47_GetVolume(), Si47_bVolume
    Result = Si47_GetProperty(cRX_VOLUME)                                   ' Read the volume value from the device
EndProc

'-------------------------------------------------------------------------------
' Alter the volume from the device
' Input     : pVolume (Si47_bVolume) holds the volume value (0 to 63)
' Output    : Returns True if the command was successful
' Notes     : None
'
Proc Si47_SetVolume(pVolume As Si47_bVolume), Bit
    If pVolume.SByte < 0 Then pVolume = 0                                   ' \ Set the limits of the volume value
    If pVolume > 63 Then pVolume = 63                                       ' /

    Result = Si47_SetProperty(cRX_VOLUME, pVolume)                          ' Send the volume value to the device
EndProc

'-------------------------------------------------------------------------------
' Set the properties of the device
' Input     : pProp holds the 16-bit property to modify
'           : pValue holds the 16-bit value to place in the property
' Output    : Returns True if the command was successful
' Notes     : None
'
Proc Si47_SetProperty(pProp As Word, pValue As Word), Bit
    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cCMD_SET_PROPERTY,
                                                      0b00000000,
                                                      pProp.Byte1,
                                                      pProp.Byte0,
                                                      pValue.Byte1,
                                                      pValue.Byte0]
    Result = Si47_Get_CTS_Resp(False)                                       ' Wait for the Si473X device to alter
EndProc

'-------------------------------------------------------------------------------
' Read a property from the device
' Input     : pProp holds the property to read
' Output    : Returns the property vale read from the device
' Notes     : None
'
Proc Si47_GetProperty(pProp As Word), Word
    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [cCMD_GET_PROPERTY,
                                                      0b00000000,
                                                      pProp.Byte1,
                                                      pProp.Byte0]

    I2CIn Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [Si47_bStatus,
                                                     WREG,
                                                     Result.Byte1,
                                                     Result.Byte0]
EndProc

'-------------------------------------------------------------------------------
' Send the cCMD_GET_REV command and receive the revision values
' Input     : None
' Output    : Returns the 8-byte response as an array
' Notes     : None
'
Proc Si47_GetRevisionData(), [8] As Byte
    Si47_Write8(cCMD_GET_REV)                                           ' Send the cCMD_GET_REV command to the device
    I2CIn Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [Si47_bStatus,      ' \
                                                     Str Result]        ' / Read the response into the byte array Si47_bRespBuffer

    Si47_Get_CTS_Resp(False)                                            ' Wait for the Si473X device to respond
EndProc

'-------------------------------------------------------------------------------
' Write to the GPIO
'
Proc Si47_GPIO(pValue As Byte)
    Si47_WriteCom8(cCMD_GPIO_CTL, pValue)
EndProc

'-------------------------------------------------------------------------------
' There is an anomaly in Si4704/05/3x-D60 firmware which can create periodic noise in audio
' Input     : None
' Output    : None
' Notes     : Silicon Labs recommends you disable this feature by sending the following bytes:
'             $12 $00 $FF $00 $00 $00. See Si47XX Programming Guide, AN332 (Rev 1.0) page 299.
'
Proc Si47_CorrectBug_FM()
    I2COut Si47_SDIO_Pin, Si47_SCLK_Pin, Si47_cAddr, [$12,
                                                      $00,
                                                      $FF,
                                                      $00,
                                                      $00,
                                                      $00]
    DelayMS 25
EndProc

Notice the use of the I2Cin and I2Cout commands? That is so the library will work on any suitable device and all the, unnecessary, changes made by microchip on the peripherals will not matter. :-)

charliecoutas

Les, any time you want to come to Bletchley, let me know and you'll get a VIP tour.

The datasheet for the SI4730 looks as though it uses SDR techniques, something I have never quite got my head around. Looking forward to you putting something out there that we can play with.

I built a single valve radio from Henry's Radio in London when I was very young. I remember soldering the parts onto the octal valve base very carefully and then fitting it into a transparent plastic case (part of the kit). It didn't work and my diagnostic skills got started at that point. I had interpreted the valve base connections looking into the socket from the valves perspective, not from below! I'm still making stupid mistakes several decades later.

Charlie

John Drew

G'day Charlie, like the time when I saved up my pocket money for weeks to buy a 958A (battery powered uhf acorn valve). I accidentally put the B battery (67V) onto the 1.4V filament which went very bright for a moment. I was making a 288MHz walkie talkie when we had the use of the one metre band in Oz.
It taught me to always check my connections several times.
Cheers,
John

top204

#7
Ahhhh The lovely little acorn valves. :-)

I remember dad had a few of them in our workshop (the garden shed), but I never got to use them because I was fascinated with Triode/Pentode valves that could do two jobs with a single valve. :-) When I was a young-un, valves were very much out of date, but I was fascinated by them, so dad showed me how to design and create circuits with them. I still remember my first amplifier with a single triode/pentode valve, and when I "finally" got it working, I was so pleased with myself. But then again, I was only about 12 years old at the time. :-)

I also remember the "battery" valves that dad had. They were small and slender with long wires coming from them, and worked off, I think, 22 volts. They used them in car radios for many years, and I think that is where dad got them from, because we could not afford new electronic components. So we salvaged what we could from things that we found lying around, or in bins and skips etc... Or what dad found when he was bricking up the doors and windows of houses that were ready for demolition. They used to brick up the openings to the houses so people would not go in and steal the copper and lead pipes and copper cables etc...

keytapper

Ah, what a lovely story. I wish one day my son will remember me as you doing Mr. Les .
But fathers may be such criticizer, that won't trust the sons ::)
Ignorance comes with a cost