AA32 RADIO FM DUT GEII TOURS

Dependents:   RadioFM

Files at this revision

API Documentation at this revision

Comitter:
jlpadiolleau
Date:
Mon Dec 16 07:37:25 2019 +0000
Commit message:
Si4735 GEII TOURS

Changed in this revision

Si4735.cpp Show annotated file Show diff for this revision Revisions of this file
Si4735.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Si4735.cpp	Mon Dec 16 07:37:25 2019 +0000
@@ -0,0 +1,397 @@
+//Modifié par VG: attention il faut diminuer la vitesse du bus SPI sur la UnoRev3 (sinon gros problème de lecture)
+//Voir ligne dans la méthode begin SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
+//j'ai ajouté 1<<SPR0 pour mettre l'horloge / 16 (Fmax du Si7435=2,5MHz !!!)
+
+
+/* Arduino Si4735 Library
+ * Written by Ryan Owens for SparkFun Electronics 5/17/11
+ * Altered by Wagner Sartori Junior 09/13/11
+ * Actively Being Developed by Jon Carrier
+ *
+ * This library is for use with the SparkFun Si4735 Shield
+ * Released under the 'Buy Me a Beer' license
+ * (If we ever meet, you buy me a beer)
+ *
+ * See the header file for better function documentation.
+ *
+ * See the example sketches to learn how to use the library in your code.
+*/
+
+/*
+
+SPCR
+| 7    | 6    | 5    | 4    | 3    | 2    | 1    | 0    |
+| SPIE | SPE  | DORD | MSTR | CPOL | CPHA | SPR1 | SPR0 |
+
+SPIE - Enables the SPI interrupt when 1
+SPE - Enables the SPI when 1
+DORD - Sends data least Significant Bit First when 1, most Significant Bit first when 0
+MSTR - Sets the Arduino in master mode when 1, slave mode when 0
+CPOL - Sets the data clock to be idle when high if set to 1, idle when low if set to 0
+CPHA - Samples data on the falling edge of the data clock when 1, rising edge when 0
+SPR1 and SPR0 - Sets the SPI speed, 00 is fastest (4MHz) 11 is slowest (250KHz)
+
+*/
+#include "Si4735.h"
+
+
+//This is just a constructor.
+//Default values are assigned to various private variables
+Si4735::Si4735()
+{
+	//busspi = new SPI(D11,D12,D13);//mosi,miso,sck
+	SPISS = new DigitalOut(D10);
+	GPO2 = new DigitalInOut(D2);//D2
+	GPO1 = new DigitalInOut(D12);//D12
+	POWER_PIN = new	DigitalOut(D8);//D8
+	RADIO_RESET_PIN = new DigitalOut(D9);//D9
+	
+	_mode		= FM;//FM par défaut
+	_locale	= EU;//europe de l'ouest
+	_volume	= 63;//volume à fond
+}
+
+void Si4735::begin(char mode)
+{
+	_mode = mode;//FM par défaut
+	//Etat RESET de l'ordinogramme
+	//On configure les broches en sorties, positionne GPO1 et GPO2 à 1 pendant le reset du Si4735
+	//pour se mettre en mode de communication SPI
+	GPO2->output();//On force pour l'instant GPO2 en sortie
+	GPO1->output();//On force pour l'instant GPO1 en sortie
+	
+	//On active la séquence reset du Si4735
+	RADIO_RESET_PIN->write(0);
+	POWER_PIN->write(0);
+	//wait_ms(20);
+	//On met un niveau 1 sur les GPO (mode SPI)
+	GPO1->write(1);
+	GPO2->write(1);
+	wait_ms(20);
+	//On alimente le Si4735
+	POWER_PIN->write(1);
+	wait_ms(20);
+	//front montant sur la broche reset du Si4735 
+	RADIO_RESET_PIN->write(1);
+	wait_ms(200);//attente pour la prise en compte du mode choisi
+
+	GPO1->input();//On remet GPO1 en entrée pour le bus SPI
+	//broche INT_PIN en entrée
+	GPO2->input();//On remet GPO2 en entrée
+	//SS au niveau haut	
+	SPISS->write(1);
+	delete GPO1;//on détruit GPO1 pour laisser la broche D12 au bus SPI
+	
+	wait(0.2);
+	//Configure le SPI, Maitre, 1MHz Mode 0 à priori pour le Si4735
+	//2,5 MHz max pour l'horloge bus SPI
+	busspi = new SPI(D11,D12,D13);//mosi,miso,sck
+	busspi->format(8,0);//8 bits de données et mode 0
+	busspi->frequency(1000000);//1 MHz
+	wait(0.2);
+	
+	//Emission de la commande POWER_UP (0x01)
+	sprintf(command, "%c%c%c", 0x01, 0x50, 0x05);//Quartz 32768Hz externe validé et sortie GPO2, sortie analogique validé
+	sendCommand(command, 3);
+	wait_ms(200);//Pas vu dans la doc ???
+
+	//Configure GPO lines to maximize stability
+	sprintf(command, "%c%c", 0x80,0x06);//GPO1 et GPO2 en sortie, GPO3 en haute impédance
+	sendCommand(command, 2);
+	wait_ms(10);
+	sprintf(command, "%c%c", 0x81,0x04);//toutes les sorties à zéro sauf GPO1 (pourquoi MISO à 1 ?)
+	sendCommand(command, 2);
+	wait_ms(10);
+
+	//Configure le volume à la valeur courante
+	setVolume(_volume);
+
+	//son sur les sorties audio
+	unmute();
+         
+    setLocale(EU);//désaccentuation Europe = 50µs (filtrage)
+    /*    
+	//Enable RDS
+	setProperty(0x1500, 0x0001);//positionne RDSINT quand la pile FIFO a des données RDS
+	setProperty(0x1501, 0x0004);//Minimum 4 groupes RDS stocké dans la FIFO (A,B,C et D)
+	//setProperty(0x1502, 0xEF01);//Validation RDS et config de la gestion des erreurs sur chaque bloc
+	//Only store good blocks and ones that have been corrected
+	setProperty(0x1502, 0xAA01);	
+	//Only store good blocks
+	//setProperty(0x1502, 0x0001);//Validation RDS et aucune erreur sur les blocs
+	*/
+    seekThresholds(2,14);//on ajuste le seuil pour rechercher plus de stations SNR=2, RSSI=14
+}
+
+
+void Si4735::tuneFrequency(uint16_t frequency)
+{
+	//Split the desired frequency into two character for use in the
+	//set frequency command.
+	uint8_t highByte = frequency >> 8;
+	uint8_t lowByte = frequency & 0x00FF;
+	
+	//set the new frequency. Mode FM uniquement
+	sprintf(command, "%c%c%c%c", 0x20, 0x00, highByte, lowByte);
+	sendCommand(command, 4);
+	wait_ms(100);
+}
+#if defined(USE_SI4735_REV)
+void Si4735::getREV(char*FW,char*CMP,char *REV)
+{
+	//FW = Firmware and it is a 2 character array
+	//CMP = Component Revision and it is a 2 character array
+	//REV = Chip Revision and it is a single character
+	char response [16]={0};
+	sprintf(command, "%c", 0x10);
+	
+	//Send the command
+	sendCommand(command, 1);
+
+	//Now read the response	
+	getResponse(response);	
+
+	FW[0]=response[2];
+	FW[1]=response[3];
+	FW[2]='\0';
+	CMP[0]=response[6];
+	CMP[1]=response[7];
+	CMP[2]='\0';
+	*REV=response[8];	
+}
+#endif //USE_SI4735_REV
+
+uint16_t Si4735::getFrequency()
+{
+	char response [16]={0};
+	uint16_t frequency=0;	
+	uint8_t highByte=0;
+	uint8_t lowByte=0;
+			
+	//The FM_TUNE_STATUS command
+	sprintf(command, "%c%c", 0x22, 0x00);
+	//Send the command
+	sendCommand(command, 2);
+
+	//Now read the response	
+	getResponse(response);
+	
+	lowByte=response[3];
+	highByte=response[2];
+        
+    frequency = (highByte<<8)+lowByte;
+    return frequency;
+}
+
+void Si4735::seekUp(void)
+{
+	//Use the current mode selection to seek up.
+	sprintf(command, "%c%c", 0x21, 0x0C);
+	sendCommand(command, 2);
+	wait_ms(1);
+}
+
+void Si4735::seekDown(void)
+{
+	//Use the current mode selection to seek down.
+	sprintf(command, "%c%c", 0x21, 0x04);
+	sendCommand(command, 2);	
+	wait_ms(1);
+}
+
+void Si4735::seekThresholds(uint8_t SNR, uint8_t RSSI)
+{
+	//Use the current mode selection to set the threshold properties.	
+	if(SNR>127)SNR=127;
+	else if(SNR<1)SNR=0;
+	if(RSSI>127)RSSI=127;
+	else if(RSSI<1)RSSI=0;
+	setProperty(0x1403, (uint16_t)SNR);	
+	setProperty(0x1404, (uint16_t)RSSI);				
+}
+
+#if defined(USE_SI4735_RSQ) 
+void Si4735::getRSQ(Metrics * RSQ)
+{
+	//This function gets the Received Signal Quality Information
+	char response [16]={0};
+				
+	//The FM_RSQ_STATUS command
+	sprintf(command, "%c%c", 0x23, 0x00);
+	//Send the command
+	sendCommand(command, 2);
+
+	//Now read the response	
+	getResponse(response);	
+
+	//Pull the response data into their respecive fields
+	RSQ->RSSI=response[4];
+	RSQ->SNR=response[5];
+
+	RSQ->STBLEND=response[3]&63;
+	RSQ->MULT=response[6];
+	RSQ->FREQOFF=response[7];
+}
+#endif
+
+uint8_t Si4735::volumeUp(void)
+{
+	//63 est le volume maximum
+	if(_volume < 63)
+	{
+		_volume+=1;
+		//Set the volume to the current value.
+		setProperty(0x4000, (uint16_t)_volume);	
+	}
+	return _volume;
+}
+
+uint8_t Si4735::volumeDown(void)
+{
+	//If we're not at the minimum volume yet, decrease the volume
+	if(_volume > 0){
+		_volume-=1;
+		//Set the volume to the current value.
+		setProperty(0x4000, (uint16_t)_volume);	
+	}
+	return _volume;
+}
+
+uint8_t Si4735::setVolume(uint8_t value)
+{
+	if(value <= 63 && value > 0){
+		_volume=value;
+		//Set the volume to the current value.
+		setProperty(0x4000, (uint16_t)_volume);
+	}
+	return _volume;
+}
+
+uint8_t Si4735::getVolume(void)
+{	
+	return _volume;
+}
+
+void Si4735::mute(void)
+{
+	setProperty(0x4001, 0x0003);//coupe le son sur les voies gauche et droite
+}
+
+void Si4735::unmute(void)
+{
+	setProperty(0x4001, 0x0000);//son L et R ok
+}
+
+char Si4735::getStatus(void)
+{
+	char response=0;
+	//SS au niveau bas
+	SPISS->write(0);
+	wait_ms(1);
+	spiTransfer(0xA0);  //Commande de lecture sur GPO1 d'un octet (MISO du SPI)
+	wait_ms(1);
+	response = spiTransfer(0x00);  //Lecture de la réponse
+	//SS au niveau haut, fin de lecture
+	SPISS->write(1);
+	return response;
+}
+
+void Si4735::getResponse(char *response)
+{
+	//char cmd=0xE0;
+	//SS au niveau bas
+	SPISS->write(0);
+	wait_ms(1);
+	busspi->write(0xE0);//Commande de lecture d'une série de 16 octets sur GPO1 (MISO)
+	//spiTransfer(0xE0);  //Commande de lecture d'une série de 16 octets sur GPO1 (MISO)
+	//wait_ms(1);
+	//lecture de 16 octets - le premier est l'octet de contrôle, puis les 15 data
+	//busspi->write(&cmd,1,response,16);
+	for(int i=0; i<16; i++) *response++ = busspi->write(0x00);  //Lecture des 16 octets
+	//SS au niveau haut, fin de lecture
+	SPISS->write(1);
+}
+
+void Si4735::end(void)
+{
+	sprintf(command, "%c", 0x11);//Commande POWER_DOWN
+	sendCommand(command, 1);
+	wait_ms(1);
+}
+
+void Si4735::setLocale(uint8_t locale)
+{
+	_locale=locale;	
+	//Set the deemphasis to match the locale
+	switch(_locale)
+	{
+		case NA:			
+			setProperty(0x1100, 0x0002);		
+			break;
+		case EU:
+			setProperty(0x1100, 0x0001);
+			break;
+		default:
+			break;
+	}
+}
+
+uint8_t Si4735::getLocale(void)
+{
+	return _locale;
+}
+
+
+void Si4735::setMode(char mode)
+{
+	end();
+	begin(mode);
+}
+
+char Si4735::getMode(void)
+{
+	return _mode;
+}
+
+//Envoie la commande 0x12 pour positionner la valeur value du paramètre situé à l'adresse address
+void Si4735::setProperty(uint16_t address, uint16_t value)
+{	
+	sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, (address>>8)&255, address&255, (value>>8)&255, value&255);
+	sendCommand(command, 6);
+	wait_ms(1);
+}
+
+//Envoie la commande 0x13 pour lire la valeur du paramètre situé à l'adresse address.
+uint16_t Si4735::getProperty(uint16_t address)
+{	
+	char response [16]={0};	
+	sprintf(command, "%c%c%c%c", 0x13, 0x00, (address>>8)&255, address&255);
+	sendCommand(command, 4);
+	getResponse(response);
+	return response[2]<<8 | response[3];
+}
+
+/*******************************************
+*
+* Private Functions
+*
+*******************************************/
+//Ecriture ou lecture sur le bus SPI !
+char Si4735::spiTransfer(char value)
+{
+	return busspi->write(value);//Emission d'un octet ou lecture
+}
+
+//Ecriture de données dans le Si4735
+//length=8 octets maximum
+void Si4735::sendCommand(char * command, int length)
+{
+  //SS au niveau bas
+  SPISS->write(0);
+  wait_ms(1);
+  spiTransfer(0x48);  //Octet de contrôle à 0x48 pour signifier une écriture dans le Si4735 (puis envoie de 8 octets de data)
+  for(int i=0; i<length; i++)spiTransfer(command[i]);
+  for(int i=length; i<8; i++)spiTransfer(0x00);  //on compléte avec des 0 si la data est < à 8 octets.
+  //Fin de la séquence par SS au niveau haut
+  SPISS->write(1);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Si4735.h	Mon Dec 16 07:37:25 2019 +0000
@@ -0,0 +1,243 @@
+/* Arduino Si4735 Library
+ * Written by Ryan Owens for SparkFun Electronics 5/17/11
+ * Altered by Wagner Sartori Junior 09/13/11 
+ * Actively Being Developed by Jon Carrier
+ *
+ * This library is for use with the SparkFun Si4735 Shield
+ * Released under the 'Buy Me a Beer' license
+ * (If we ever meet, you buy me a beer)
+ *
+ * See the example sketches to learn how to use the library in your code.
+*/
+
+//Modifié par VG pour fonctionner sous MBED
+//14 Decembre 2017
+#include "mbed.h"
+
+#ifndef __SI4735_H
+#define __SI4735_H
+
+
+//#include <string.h>
+//#include <stdio.h>
+#include <ctype.h> //toupper
+
+//Ajouter par VG pour redéfinir les constantes Arduino INPUT, OUTPUT, LOW et HIGH
+//#define INPUT	0
+//#define OUTPUT	1
+//#define LOW		0
+//#define HIGH	1
+
+
+#define READ_DELAY 10
+//Comment out these 'defines' to strip down the Si4735 library features.
+//This will help you save memory space at the cost of features.
+#define USE_SI4735_REV
+#define USE_SI4735_RDS
+#define USE_SI4735_CALLSIGN
+#define USE_SI4735_PTY
+#define USE_SI4735_RADIOTEXT
+#define USE_SI4735_DATE_TIME
+#define USE_SI4735_RSQ
+
+//List of possible modes for the Si4735 Radio
+#define AM	0
+#define FM	1
+#define SW	2
+#define LW	3
+
+//Define the Locale options
+#define NA 0
+#define EU 1
+
+#define ON	true
+#define OFF	false
+
+#define MAKEINT(msb, lsb) (((msb) << 8) | (lsb))
+
+struct Metrics {
+	uint8_t STBLEND;
+	uint8_t RSSI;
+	uint8_t SNR;
+	uint8_t MULT;
+	uint8_t FREQOFF;
+};
+
+
+class Si4735// : public SPIClass
+{
+	public:
+		//This is just a constructor.		
+		Si4735();
+		/*
+		* Description: 
+		*	Initializes the Si4735, powers up the radio in the desired mode and limits the bandwidth appropriately.
+		* 	This function must be called before any other radio command.
+		*	The bands are set as follows:
+		*	FM - 87.5 - 107.9 MHz
+		*	AM - 520 - 1710 kHz
+		*	SW - 2300 - 23000 khz
+		*	LW - 152 - 279 kHz
+		* Parameters:
+		*	mode - The desired radio mode. Use AM(0), FM(1), SW(2) or LW(3).
+		*/
+		void begin(char mode);
+		
+		/*
+		* Description: 
+		*	Acquires certain revision parameters from the Si4735 chip
+		* Parameters:
+		*	FW = Firmware and it is a 2 character array
+		*	CMP = Component Revision and it is a 2 character array
+		*	REV = Chip Revision and it is a single character
+		*/
+		#if defined(USE_SI4735_REV)
+		void getREV(char*FW,char*CMP,char *REV);
+		#endif
+
+		/*
+		* Description: 
+		*	Used to to tune the radio to a desired frequency. The library uses the mode indicated in the
+		* 	begin() function to determine how to set the frequency.
+		* Parameters:
+		*	frequency - The frequency to tune to, in kHz (or in 10kHz if using FM mode).
+		*/
+		void tuneFrequency(uint16_t frequency);
+
+		//Gets the frequency of the currently tuned station	
+		uint16_t getFrequency();
+
+
+		//	Commands the radio to seek up to the next valid channel. If the top of the band is reached, the seek
+		//	will continue from the bottom of the band.
+		void seekUp(void);
+
+		//	Commands the radio to seek down to the next valid channel. If the bottom of the band is reached, the seek
+		//	will continue from the top of the band.
+		void seekDown(void);
+		
+		/*
+		* Description:
+		*	Adjust the threshold levels of the seek function.
+		* FM Ranges:
+		*	SNR=[0-127], FM_default=3 dB
+		*	RSSI=[0-127], FM_default=20 dBuV
+		* AM Ranges:
+		*	SNR=[0-63], AM_default=5 dB
+		*	RSSI=[0-63], AM_default=19 dBuV
+		*/	
+		void seekThresholds(uint8_t SNR, uint8_t RSSI);
+
+		//	Retreives the Received Signal Quality Parameters/Metrics.
+		#if defined(USE_SI4735_RSQ)
+		void getRSQ(Metrics * RSQ);
+		#endif	
+
+		//	Sets the volume. If of of the 0 - 63 range, no change will be made.
+		uint8_t setVolume(uint8_t value);
+
+		//	Gets the current volume.
+		uint8_t getVolume(void);
+
+		//	Increasese the volume by 1. If the maximum volume has been reached, no increase will take place.
+		uint8_t volumeUp(void);
+		
+		//	Decreases the volume by 1. If the minimum volume has been reached, no decrease will take place.
+		uint8_t volumeDown(void);
+		
+
+		//	Coupe la sortie audio
+		void mute(void);
+
+		//	Disables the mute.
+		void unmute(void);
+
+		/*
+		* Description:
+		*	Gets the current status of the radio. Learn more about the status in the Si4735 datasheet.
+		* Returns:
+		*	The status of the radio.
+		*/
+		char getStatus(void);
+		
+		/*
+		* Description:
+		*	Gets the long response (16 characters) from the radio. Learn more about the long response in the Si4735 datasheet.
+		* Parameters:
+		*	response - A string for the response from the radio to be stored in.
+		*/
+		void getResponse(char * response);
+
+		//	Powers down the radio
+		void end(void);
+
+		//	Sets the Locale. This determines what Lookup Table (LUT) to use for the pyt_LUT.
+		void setLocale(uint8_t locale);
+
+		//	Gets the Locale.
+		uint8_t getLocale(void);
+
+		//	Gets the Mode of the radio [AM,FM,SW,LW]
+		char getMode(void);
+
+		/*
+		* Description:
+		*	Sets the Mode of the radio [AM,FM,SW,LW]. This also performs a powerdown operation.
+		*	The user is responsible for reissuing the begin method after this method has been called.
+		*/
+		void setMode(char mode);
+
+		//	Sets a property value
+		void setProperty(uint16_t address, uint16_t value);
+		
+		/*
+		* Description:
+		*	Gets a property value.
+		* Returns:
+		*	The value stored in address.
+		*/
+		uint16_t getProperty(uint16_t address);
+
+	private:
+		SPI *busspi;//(DATAOUT, DATAIN, SPICLOCK); // mosi, miso, sclk
+		DigitalOut *SPISS;
+		DigitalInOut *GPO2;//D2
+		DigitalInOut *GPO1;//D12
+		DigitalOut *POWER_PIN;//D8
+		DigitalOut *RADIO_RESET_PIN;//D9
+		
+		
+		char _mode; 				//Contains the Current Radio mode [AM,FM,SW,LW]		
+		char _volume;				//Current Volume
+		uint16_t _frequency;		//Current Frequency
+		uint8_t _locale; 			//Contains the locale [NA, EU]	
+
+		/*
+		* Command string that holds the binary command string to be sent to the Si4735.
+		*/
+		char command[9];	
+		
+		/*
+		* Description:
+		*	Sends a binary command string to the Si4735.
+		* Parameters:
+		*	command - Binary command to be sent to the radio.
+		*	length - The number of characters in the command string (since it can't be null terminated!)
+		* TODO:
+		*	Make the command wait for a valid CTS response from the radio before releasing 				control of the CPU.
+		*/
+		void sendCommand(char * command, int length);
+		
+		/*
+		* Description:
+		*	Sends/Receives a character from the SPI bus.
+		* Parameters:
+		*	value - The character to be sent to the SPI bus.
+		* Returns:
+		*	The character read from the SPI bus during the transfer.
+		*/
+		char spiTransfer(char value);	
+		
+};
+
+#endif