opencardev / crankshaft

Crankshaft: A turnkey GNU/Linux solution that transforms a Raspberry Pi to an Android Auto head unit.
http://getcrankshaft.com
GNU General Public License v3.0
2.15k stars 261 forks source link

Radio FM Screen Control #288

Closed cansi22 closed 2 years ago

cansi22 commented 5 years ago

There are Radio FM modules like RDA5807M and TEA5767 that are compatible with arduino and raspi. Is there any chance of having a control screen like the USB music player?

Both modules control via i2c BUS

http://cxem.net/tuner/files/tuner84_RDA5807M_datasheet_v1.pdf https://www.sparkfun.com/datasheets/Wireless/General/TEA5767.pdf

I was doing some tests with arduino and it worked

gcharlie commented 5 years ago

I ran into a pretty feature rich FM app for Raspberry Pi that uses RTL-SDR modules. I don't know if it can be looped into Crankshaft directly, but maybe a similar feature can be implemented in the future.

https://www.elektormagazine.com/labs/piradio-for-fm-radio-receiver-with-rds-for-raspberry-pi-160520-1

hawkeyexp commented 5 years ago

I was planning to include wello.io caused by the fact that more and more countries are canceling the classic fm radio and switching to dab based broadasts. I will do some experiments next time.

cansi22 commented 5 years ago

I ran into a pretty feature rich FM app for Raspberry Pi that uses RTL-SDR modules. I don't know if it can be looped into Crankshaft directly, but maybe a similar feature can be implemented in the future.

https://www.elektormagazine.com/labs/piradio-for-fm-radio-receiver-with-rds-for-raspberry-pi-160520-1

Umm

Implementing it by software (SDR) would be more convenient, so it is not necessary to use the audio output of the FM module to the amplifier. The sound card would be used for it.

I'll look for a receiver to prove it 👍

I was planning to include wello.io caused by the fact that more and more countries are canceling the classic fm radio and switching to dab based broadasts. I will do some experiments next time.

In Spain, we only have FM radio.I think DAB is implemented, but nobody uses it. We all use FM receivers

renne commented 5 years ago

The welle.io gui isn't car friendly. DAB(+) with automatic FM fallback would be great.

xstsx commented 5 years ago

Actually recent I was doing some "researching" how to add simple FM module to RPi without additional external components. So what I got for now:

Si4735 FM module with RDS. Control - I2C bus + Reset pin. (3 pins) Audio - I2S. (+feeding si4735 system clock). (3 pins)

RPi side. Simple python script to control. I2S master input routed to I2S out via loopback.

It's working pretty good for proof of concept. Maybe something like this setup will make the goal for you.

hawkeyexp commented 5 years ago

We will see what can be done - intial i start experimenting with wello

dabshield commented 5 years ago

Hello all,

This is my first post - but I may have something to contribute. I developed the DabShield SiLabs DAB/FM Arduino board, (dabshield.com) I've been working on creating a USB Audio Device from the Arduino so that it can be plugging into a PC/Kodi/Pi to give digital audio and also so that it can be controlled and radio text back via a HID interface. I was wanting to get a little further with my project before announcing it - but now seems a good time. I have got the Audio Class working (there isn't one as part of Arduino), and also got the Digital Audio playing through the USB - but I haven't done anything regarding the control yet.

The board could be controlled directly from the Pi, via SPI and some IO lines, but it could also have a arduino to act as controller for the board, and communicate with the Pi using say UART, USB etc. The board has both analogue and I2S (Master or Slave).

I work for the automotive industry developing audio systems - so perhaps I could help ?

Thanks, Adrian

renne commented 5 years ago

@dabshield I suggest a DAB(+)/FM RPi hat with 2x TI TAS5756M connected via I2S/TDM to the RPI to drive front and rear stereo speakers of a car.

The hat should supply power to the RPi with ignition managament.

A GPS/Galileo/Glonass/Beidou receiver for an external antenna would be great, too. And an inductive coupler RPi3(+) WLAN antenna to external antenna.

gcharlie84 commented 5 years ago

One thing to note about DAB is that it's not used in North America at all. Canada and the US moved to HDRadio (NRSC-5-D) for digital radio broadcast, it's used in tandem with regular analog FM. But looks like some work has been done to decode and playback NRSC-5-D using the rtl-sdr which is what welle.io uses as well.

https://www.rtl-sdr.com/decoding-and-listening-to-hd-radio-nrsc-5-with-an-rtl-sdr/

HahnRobin commented 5 years ago

Hi everyone! I'm testing the RDA5807M, the SI4735 and an USB module with RTL2832U. I'm making a software that can support all three of these (and also the TEA5767) specially for using with Crankshaft and Raspberry Pi. With the RDA,SI,TEA modules you can use a simple sound mux or an audio processor and you can control that from the GPIO pins or I2C too. I started to design my own PCB for this purpose and this carried me away a bit from the software side for the last some weeks, but I plan to release soon the software for it. The RDA, SI modules works good and you can get RDS too, the TEA doesn't have RDS. I don't know yet if the software will support the RTL module too. I'm also working on the interface for it (in OpenAuto).

The software is done in C++, so it can be directly integrated in OpenAuto if needed, but I think as a separate executable it would be better.

borconi commented 5 years ago

Ok, this is a bit more complex, Android Auto does have something for radio, but not sure if the full implementation is there. I will keep it basic on what's needed (in theory as I haven't done this):

1) An FM/AM receiver (or DAB) 2) The headunit software being able to handle the radio receiver (to make calls to the RTL/RDS unit, to tune, save channel etc) 3) To implement the Radio ProtoBuff it is NOT available in AASDK ( https://github.com/f1xpl/aasdk/tree/development/aasdk_proto ) but it does exists, I've started it decoding it once, but gave up as I did not had time and since I'm working with Android units I do not have the means to access the FM module so for me it was out of scope to do this. Another user did this (slash_max, the one who created AAMirror), so I'm going to insert it at the bottom of my post here. 4) An app on the car side which will be able to handle this, theoretically, AA should be able to do it, but I think they never finished developing this function of Android Auto.

ProtoBuff for radio (needs slight adjustment, but generally this is it) :


enum RadioType
{
    RADIOTYPE_DEFAULT = 0;
}
enum RadioMessageId
{
    RADIOMESSAGEID_DEFAULT = 0;
}

//NOTE YOU NEED TO DECLARE IT AS A RADIO SERVICE!!!!!!
message Service
{
    optional int32 id = 1;
    optional SensorSourceService sensor_source_service = 2;
    optional MediaSinkService media_sink_service = 3;
    optional InputSourceService input_source_service = 4;
    optional MediaSourceService media_source_service = 5;
    optional BluetoothService bluetooth_service = 6;
    optional RadioService radio_service = 7;
    optional NavigationStatusService navigation_status_service = 8;
    optional MediaPlaybackStatusService media_playback_service = 9;
    optional PhoneStatusService phone_status_service = 10;
    optional MediaBrowserService media_browser_service = 11;
    optional VendorExtensionService vendor_extension_service = 12;
    optional GenericNotificationService generic_notification_service = 13;
}

message RadioService
{
    repeated RadioProperties radio_properties = 1;
}

message RadioProperties
{
    optional int32 radio_id = 1;
    optional RadioType type = 2;
    repeated Range channel_range = 3;
    repeated int32 channel_spacings = 4;
    optional int32 channel_spacing = 5;
    optional bool background_tuner = 6;
    optional ItuRegion region = 7;
    optional RdsType rds = 8;
    optional bool af_switch = 9;
    optional bool ta = 10;
    optional TrafficServiceType traffic_service = 11;
    optional bool audio_loopback = 12;
    optional bool mute_capability = 13;
    optional int32 station_presets_access = 14;
}

message RadioStateNotification
{
    optional bool radio_source_enabled = 1;
    optional bool radio_muted = 2;
    optional int32 active_radio_id = 3;
    optional RadioStationInfo station_info = 4;
    repeated RadioStationInfo program_list = 5;
    repeated StationPresetList station_preset_lists = 6;
}

message RadioSourceRequest
{
}

message RadioSourceResponse
{
    optional MessageStatus status = 1;
    optional bool radio_source_enabled = 2;
}

message SelectActiveRadioRequest
{
    optional int32 radio_id = 1;
}

message ActiveRadioNotification
{
    optional MessageStatus status = 1;
    optional int32 radio_id = 2;
    optional RadioStationInfo station_info = 3;
}

message StepChannelRequest
{
    optional int32 radio_id = 1;
    optional bool up = 2;
    optional bool skip_sub_channel = 3;
}

message StepChannelResponse
{
    optional MessageStatus status = 1;
    optional int32 radio_id = 2;
}

message SeekStationRequest
{
    optional int32 radio_id = 1;
    optional bool up = 2;
    optional bool skip_sub_channel = 3;
}

message SeekStationResponse
{
    optional MessageStatus status = 1;
    optional int32 radio_id = 2;
}

message ScanStationsRequest
{
    optional int32 radio_id = 1;
    optional bool start = 2;
    optional bool up = 3;
    optional bool skip_sub_channel = 4;
}

message ScanStationsResponse
{
    optional MessageStatus status = 1;
    optional int32 radio_id = 2;
    optional bool started = 3;
}

message TuneToStationRequest
{
    optional int32 radio_id = 1;
    optional int32 channel = 2;
    optional int32 sub_channel = 3;
}

message TuneToStationResponse
{
    optional MessageStatus status = 1;
    optional int32 radio_id = 2;
}

message RadioStationInfoNotification
{
    optional int32 radio_id = 1;
    optional RadioStationInfo station_info = 2;
}

message RadioStationInfo
{
    optional RadioType type = 1;
    optional int32 channel = 2;
    optional int32 sub_channel = 3;
    optional RadioStationMetaData meta_data = 4;
}

message RadioStationMetaData
{
    optional int32 audio_channels = 1;
    optional int32 signal_quality = 2;
    optional RdsData rds = 3;
    optional HdRadioStationInfo hd_station_info = 4;
}

message RdsData
{
    repeated int32 alternative_frequencies = 1;
    optional int32 program_id = 2;
    optional int32 music_speech_switch = 3;
    optional string program_service_name = 4;
    optional int32 program_type = 5;
    optional string program_type_name = 6;
    optional string radio_text = 7;
    optional bool traffic_program_flag = 8;
    optional bool traffic_announcement_flag = 9;
}

message HdRadioStationInfo
{
    optional HdAcquisionState acquisition_state = 1;
    optional int32 digital_signal_strength = 2;
    optional HdRadioPsdData psd = 3;
    optional HdRadioSisData sis = 4;
}

message HdRadioPsdData
{
    optional string title = 1;
    optional string artist = 2;
    optional string album = 3;
    optional string genre = 4;
    optional HdRadioComment comment = 5;
    optional HdRadioCommercial commercial = 6;
    optional HdRadioArtistExperience artist_experience = 7;
}

message HdRadioComment
{
    optional string description = 1;
    optional string text = 2;
}

message HdRadioCommercial
{
    optional int32 encoding = 1;
    optional string price = 2;
    optional string valid = 3;
    optional string url = 4;
    optional int32 received = 5;
    optional string seller = 6;
    optional string description = 7;
}

message HdRadioArtistExperience
{
    optional bytes image = 1;
}

message HdRadioSisData
{
    optional int32 station_id = 1;
    optional string station_name_short = 2;
    optional string station_name_long = 3;
    optional Location station_location = 4;
    optional string station_message = 5;
    optional string service_info_message = 6;
    optional string universal_short_station_name_slogan = 7;
}
krisstakos commented 5 years ago

I have different aproach for bringing regular FM radio in the crankshaft but I need some help. So to the idea: Crankshaft supports .strm files and there is rtl_fm_streamer which turns generic rtl-sdr dongle in to internet radio streamer and can be accessed trough the assigned local ip address of the pi + there is JSON RPC api for setting the frequency. I successfully compiled and tested the streamer. And tried making local file which contains the streaming address but the sound is choppy. So I dig around in the crankshaft source and guesed that for playing media it uses gst-launch-1.0(gstreamer)? (if anyone more familliar with the source can confirm it would be nice) I continue with my research and replicated exact choppy sound using mentioned tool and modifed my command so I can listen to the stream without problems. Working command: gst-launch-1.0 souphttpsrc location=http://localhost:2346/103800000/1 ! rawaudioparse use-sink-caps=false format=pcm pcm-format=s16le sample-rate=48000 num-channels=2 ! audioconvert ! audioresample ! autoaudiosink The problem: I need your help to integrate it. The idea is when the user press .strm, the executor looks inside the file and if there is 'localhost' in the address execute with the right command. The goal: You can make files with your favourite radios and just play them using only rtl-sdr dongle

github-actions[bot] commented 2 years ago

This issue is stale because it has been open 120 days with no activity. Remove stale label or comment or this will be closed in 60 days.

github-actions[bot] commented 2 years ago

This issue was closed because it has been stalled for 60 days with no activity.