B4R Question A Library for Si4703_Breakout

derez

Expert
Licensed User
Longtime User
Can anyone wrap the attached library for B4R ?
It is for a tuner board :
upload_2017-7-7_22-25-16.png

Thanks
 

Attachments

  • Si4703_Breakout.zip
    6.4 KB · Views: 498

Peter Simpson

Expert
Licensed User
Longtime User
Hey @derez I ordered this one from AliExpress on 04:11 June 18 2017 CLICK HERE. I previously looked at the Arduino IDE code and decided to use a time and try to mix and match B4X code with Inline C when I receive my Si4703 FM tuner next week.

I'm more than sure that somebody will wrap this for you shortly. Hey, if somebody does wrap it, I can then use it too :)

So what are you going to do with your Si4703?
 
Last edited:
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Hello @derez
Sorry I missed your last post with the zip file.

Did you get it working using Inline C?
Errors, once I commented out // poweron(); it compiled with no errors on my UNO?

I'm just reading my learning C++ book, only because I have about 30 minutes spare before I go out for a tot :)
 
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
Hello @derez
Sorry I missed your last post with the zip file.

Did you get it working using Inline C?
No, for a reason I can't understand, I get errors for all the functions saying that the function is not recognized in the cpp file. I commented all but the poweron which is the simplest, but to no avail.
I'm not sure that the first declaration (#define...) is correct.
I'm frustrated because there is no tutorial, just examples.
Keep learning, maybe the answers will come from you !
Erel promised to write the library when his Si comes.
 
Last edited:
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Hiya @derez,
If you have now got your radio module you could always use this code until Erel receives his module and kindly creates a library for the community. The code below is completely untested but hopefully it will work perfect for you. I've not received my radio module as yet so I can't test the code either.

Edited: I've just added 2 extra functions (subs) in the code below to search up and down for radio stations, you can just call the required function at will.

Use the following 2 lines to search for stations, the channel will set automatically:
B4X:
RunNative("seekup", Null);
RunNative("seekdown", Null);

Main code to use:
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public Serial1 As Serial

    Private TmrRadio As Timer
    Private channel As Int 'Ignore
    Private volume As Int 'Ignore
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")

    Log("Si4703_Breakout Test For B4R")
    Log("============================")
    Log("a b     Favourite stations")
    Log("+ -     Volume (max 15)")
    Log("u d     Seek up / down")
    Log("r       Listen for RDS Data (15 sec timeout)")
    Log("Send me a command letter.")

    RunNative("setup", Null)

    volume = 5
    'channel = 0

    TmrRadio.Initialize("TmrRadio_Tick", 1)
    TmrRadio.Enabled = True
End Sub

Sub TmrRadio_Tick
    RunNative("radioloop", Null)
End Sub

#if C

#include <Si4703_Breakout.h>

int resetPin = 2;
int SDIO = A4;
int SCLK = A5;

Si4703_Breakout radio(resetPin, SDIO, SCLK);
char rdsBuffer[10];

void setup(B4R::Object* unused)
{
  Serial.println("Power On");
  radio.powerOn();
  Serial.println("Set Volume");
  radio.setVolume(0);
}

void displayInfo()
{
   Serial.print("Channel:"); Serial.print(b4r_main::_channel);
   Serial.print(" Volume:"); Serial.println(b4r_main::_volume);
}

void radioloop(B4R::Object* unused)
{
  if (Serial.available())
  {
    char ch = Serial.read();
    if (ch == 'u')
    {
       b4r_main::_channel = radio.seekUp();
      displayInfo();
    }
    else if (ch == 'd')
    {
      b4r_main::_channel = radio.seekDown();
     displayInfo();
    }
    else if (ch == '+')
    {
      b4r_main::_volume ++;
      if (b4r_main::_volume == 16) b4r_main::_volume = 15;
      radio.setVolume(b4r_main::_volume);
     displayInfo();
    }
    else if (ch == '-')
    {
      b4r_main::_volume --;
      if (b4r_main::_volume < 0) b4r_main::_volume = 0;
      radio.setVolume(b4r_main::_volume);
     displayInfo();
    }
    else if (ch == 'a')
    {
      b4r_main::_channel = 930; // Rock FM
      radio.setChannel(b4r_main::_channel);
     displayInfo();
    }
    else if (ch == 'b')
    {
      b4r_main::_channel = 974; // BBC R4
      radio.setChannel(b4r_main::_channel);
     displayInfo();
    }
    else if (ch == 'r')
    {
      Serial.println("RDS listening");
      radio.readRDS(rdsBuffer, 15000);
      Serial.print("RDS heard:");
      Serial.println(rdsBuffer);
    }
  }
}

void seekup(B4R::Object* unused)
{
    b4r_main::_channel = radio.seekUp();
}

void seekdown(B4R::Object* unused)
{
    b4r_main::_channel = radio.seekDown();
}

#End If

Enjoy...
 
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
Big Help !!!:)
With your code on the screen I managed to make the inline c code, except for one problem - passing the rdsBuffer from the c code to the b4r code - the last commented line.
As I have suspected the problem was in the first definition.
Just remember - I also don't have the Si board yet... but ordered an amplifier and few potentiometers with knobs. Speakers - I already have from broken toys.
 

Attachments

  • Radio2.zip
    1.5 KB · Views: 377
Last edited:
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Good morning @derez,
My Si4703 turned up this morning, after connecting it up I got it working perfect with Inline C.

To test the module I decided to create an accompanying B4J radio control app to send the commands to the Si4703 rather than using either an Android device with MQTT or placing the Si4703 on a breadboard with 2 rotary encoders and using it that way, I was basically too lazy so I turned to B4J as it was the quickest way to test the Si4703 with receiving external commands :)

I was having problems storing the RDS data in a Globals Private rdsdata() As Byte, it just kept returning 163, 171 or other strange values when trying to read back the byte array :mad:, maybe I should post a question about it. I know that you just can't save strings directly from Inline C to global strings, but for some strange reason it wasn't working for me, so I just cheated instead, my solution is not nice but it works perfect, I'll post a question about it to try and get the correct solution.

Anyway, the Si4703 is an okay bit of kit for the price and it works as expected, nothing special though. It does not pick up as many stations as I first thought it would do (no surprises there then), it uses the headphone cable as the antenna, also the RDS needs a really good signal to pick up the station names.

I have found an Arduino library that has plenty of extra features like manual or auto seek, test for stereo or mono, signal strength, ower off, AFT, AT etc, but the library will need wrapping.

If @Erel wants to see the updated library I will post it on here, he did say he had ordered the board and would wrap the library that you posted, the library that I've found has more features/functions.

The B4J app that I created is really easy to use. Just make sure that your Si4703 is connected to your Arduino, plug it onto your computer/laptop and run the B4J app. Press the search buttons to find a channel, once found press the RDS button to get the RDS information if the signal is strong enough. The app just send the commands via AStreams and reads the response that is then displayed in the app.

If Erel wasn't going to wrap this library, I would have gladly created a code snippet post for the Si4703, well the other library as it has more features. But it will be a complete waste of time if I created a post knowing that there will be a library on here shortly for the same module.

CLICK HERE to download the B4J test app for controlling the Si4703 radio module.
  • WIRE LEGEND for Si4703 radio receiver
  • SDIO = A4
  • SCLK = A5
  • RST = 2
  • GND = GND
  • 3.3V = 3.3V
B4J radio control panel for Si4703.
Radio.jpg


Enjoy...
 
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
Got my board and put everything together: Arduino UNO, Realtime clock,LCD and the radio.
Everything works except that I don't get results from the RDS, even by running the original arduino program.
I made a workaround by a list of names in the application.

radio.jpg
 
Last edited:
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Wow @derez that's looks great, it really does.
So when are you going to buy a 3D printer so that you can print a nice housing to put your project in ;)

RDS issue:
The problem with the RDS is that you need a really good signal for the module to pick up the RDS data. I'm lucky as my house is almost on top of a hill and I receive the RDS with ease. I plugged in a JBL speaker and the signal jumped up, and RDS suddenly started to work even better.

BTW the library that you are using does not have signal or stereo. I took a couple of methods out of another library and put them into the library that you posted then just used Inline C to manipulate it, if you want the updated library I'll send it to you :)
 
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Hiya @derez,
I've just ordered an 'Audio Amplifier', well actually I've just ordered 4, cheers ;).

I've just taken out some of the extra methods that I put in which I didn't use fully, these were getAF, getPTY (I rarely used) and setQuality (I think it worked but I will test again in the future), but I've left the main two that I added and use from another library.

int getRSSI();
int getStereo();

getRSSI(Int):
Returns the signal strength measured in dBm (decibel milliwatts), the signal ranges from 0 to -100, -100 being a very strong signal. RSSI is why my app has a signal reading when the library that you originally posted does not have one.

Hint for auto tuning-
I found code that was seriously difficult for me to translate from C++ that somehow manipulated the modules to auto search for channels. I decided to use a timer to search up/down the frequency and also the signal strength at the same time, if the signal is >=10 then the auto search will stop, simple but effective. The original does not use any timers but being that I'm still learning C++ in my spare time it was not easy for me to decipher, so using a timer in B4R was more than adequate for my needs.

getStereo(Boolean):
Returns the signal status either stereo or mono. I have a little red dot on my display (not visible in the above screen shot) which becomes visible when the module is receiving a full stereo signal.

I decided to attach the library to this post instead of emailing it to you.

Enjoy...
 

Attachments

  • Si4703_Breakout.zip
    5.2 KB · Views: 389
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
I added these functions to the inline code :
B4X:
void GetStereo(B4R::Object* unused) {
   b4r_main::_stereo = radio.getStereo();   
}
  
void GetRSSI(B4R::Object* unused) {
   b4r_main::_rssi = radio.getRSSI();   
}

I get stereo mostly 0, very rare and only momentary 1 (but it works).
The RSSI follows the quality of sound... your number 10 looks right.

Edit: when disconnected from the usb cable the reception became better and I got stereo 1 for many cases.
 
Last edited:
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Edit: when disconnected from the usb cable the reception became better and I got stereo 1 for many cases.

Really, I've not noticed that, that's extremely interesting to know, cheers :D. I've ordered an amp that one that you posted yesterday and it should be with me in a couple of weeks.

You should try to add auto station search, now that you have a read signal strength method it will be easy enough to implement.

Peter...
 
Upvote 0

derez

Expert
Licensed User
Longtime User
the subs to find a station:
B4X:
Sub pin9_StateChanged(state As Boolean) ' seek up
    If state Then
        RunNative("SeekUp",Null)
        RunNative("GetRSSI",Null)
        If Rssi < 15 Then find_station(True)
        show_frequency
        show_name
    End If
End Sub

Sub find_station(up As Boolean)
    Do While Rssi < 15
        If up Then
            RunNative("SeekUp",Null)
        Else
            RunNative("SeekDown",Null)
        End If
        RunNative("GetRSSI",Null)
    Loop
End Sub

pin 8 does the same with parameter false to search down.
 
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Hey I like that, I'll use that instead of a timer @derez, 'Do While' never even crossed my mind at the time, thank you.

I knew that you would come in handy for some code sooner or later, it's only taken about 100 years though lol :p

I've seen C++ code based on your original library that does auto channel search, but figuring it out was like repairing the Star Ship Enterprise warp nacelles. I looked at the IC specification for the Si4703 and I recognised instantly the initials RSSI and that's why I decided to use that for auto channel search and not spend hours or even days trying to convert C++ code that I don't even understand

Anyway I can't wait to see you finished product @derez, it should be good. I'm also please that you motivated me to spend more time looking at the radio module and I probably would not have done as much as I did and also learn as much.

I tried wrapping the library but there were a few errors, I'll have another go next week what I get a few hours spare to fail again :mad:
 
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
Received the amplifier and connected it instead of earphones, + two speakers. It works but I have found that you can't leave the device alone to play... you have to hold the output wire so that it functions as antenna, while when you use earphones you are there anyway.
The amplifier is very basic - no control at all on the output audio (I didn't expect much from something that costs 0.16 $).
Decision - use with earphones only.
 
Upvote 0
Top