Arduino Radio Library  0.9
A set of Arduino libraries to control diverse FM radio receiver chips in Arduino projects.
Macros | Enumerations | Functions | Variables
WebRadio.ino File Reference

Radio implementation using a web frontend served by the Arduino. More...

#include <SPI.h>
#include <Wire.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <SD.h>
#include <SI4705.h>
#include <RDSParser.h>
#include <LiquidCrystal_PCF8574.h>
#include <RotaryEncoder.h>
#include <OneButton.h>
#include "StringBuffer.h"

Macros

#define ENCODER_FALLBACK   (3*1000)
 after 3 seconds no turning fall back to tune mode. More...
 
#define DEBUGTEXT(txt)   { Serial.print('>'); Serial.println(txt); }
 
#define DEBUGFUNC0(fn)   { Serial.print('>'); Serial.print(fn); Serial.println("()"); }
 
#define DEBUGFUNC1(fn, v)   { Serial.print('>'); Serial.print(fn); Serial.print('('); Serial.print(v); Serial.println(')');}
 
#define DEBUGVAR(l, v)   { Serial.print('>'); Serial.print(l); Serial.print(": "); Serial.println(v); }
 
#define DEBUGIP(l, n)   { Serial.print('>'); Serial.print(l); Ethernet.n().printTo(Serial); Serial.println(); }
 
#define NUL   '\0'
 
#define CR   '\r'
 
#define LF   '\n'
 
#define SPACE   ' '
 
#define REDIRECT_FNAME   "/redirect.htm"
 The filename on the disk that is used when requesting the root of the web. More...
 
#define BUFSIZ   256
 
#define CRLF   F("\r\n")
 
#define HTTP_200   F("HTTP/1.1 200 OK\r\n")
 
#define HTTP_CT   F("Content-Type: ")
 
#define HTTP_200_CT   F("HTTP/1.1 200 OK\r\nContent-Type: ")
 
#define HTTPERR_404   F("HTTP/1.1 404 Not Found\r\n")
 
#define HTTP_GENERAL   F("Server: Arduino\r\nConnection: close\r\n")
 
#define HTTP_NOCACHE   F("Cache-Control: no-cache\r\n")
 
#define HTTP_ENDHEAD   CRLF
 
#define HTML_OPEN   "<html><head></head><body>"
 
#define HTML_CLOSE   F("</body></html>")
 

Enumerations

enum  RADIO_STATE {
  STATE_PARSECOMMAND, STATE_PARSEINT, STATE_EXEC, STATE_NONE = 0,
  STATE_PARSECOMMAND, STATE_PARSEINT, STATE_EXEC, STATE_FREQ,
  STATE_VOL, STATE_MONO, STATE_SMUTE, STATE_PARSECOMMAND,
  STATE_PARSEINT, STATE_EXEC, STATE_NONE = 0, STATE_PARSECOMMAND,
  STATE_PARSEINT, STATE_EXEC, STATE_FREQ, STATE_VOL,
  STATE_MONO, STATE_SMUTE
}
 State definition for this radio implementation. More...
 
enum  WebServerState
 

Functions

RotaryEncoder encoder (A9, A8)
 Setup the RotaryEncoder. More...
 
OneButton menuButton (A10, true)
 Setup a Menu Button. More...
 
OneButton seekButton (A11, true)
 Setup a seek button. More...
 
LiquidCrystal_PCF8574 lcd (0x27)
 get a LCD instance More...
 
enum WebServerState __attribute__ ((packed))
 
EthernetServer server (80)
 
void runRadioJSONCommand (char *cmd, int16_t value)
 --— forwards --— More...
 
void runRadioSerialCommand (char cmd, int16_t value)
 
void setupRadio ()
 Setup a FM only radio configuration with I/O for commands and debugging on the Serial port. More...
 
void loopRadio (unsigned long now)
 Check once new radio data. More...
 
void respondRadioData ()
 
void loopSerial (unsigned long now)
 setupSerial More...
 
void loopWebServer (unsigned long now)
 
void loopButtons (unsigned long now)
 –— Rotary encoder and buttons –— More...
 
void setupLCD ()
 Setup the LCD display. More...
 
void loopLCD (unsigned long now)
 Constantly check for new LCD data to be displayed. More...
 
char * _ctFind (char *table, char *key)
 –— Web Server interface –— More...
 
char * _ctNextWord (char *text)
 
char * _ctCopyWord (char *text, char *word, int len)
 
void respond404NotFound ()
 
void respondEmptyFile ()
 
void respondFileList ()
 
void respondSystemInfo ()
 
void readRequestLine ()
 Read one line of text from _client into the _readBuffer. More...
 
void respondFileContent (char *fName)
 Responds the content of a file from the SD disk given by fName. More...
 
void DisplayFrequency ()
 –— LCD functions –— More...
 
void DisplayServiceName (char *name)
 
void DisplayText (char *text)
 
void DisplayTime (uint8_t hour, uint8_t minute)
 
void DisplayVolume (uint8_t v)
 
void DisplayMono (uint8_t v)
 Display the current mono switch. More...
 
void DisplaySoftMute (uint8_t v)
 Display the current soft mute switch. More...
 
void RDS_process (uint16_t block1, uint16_t block2, uint16_t block3, uint16_t block4)
 
void doMenuClick ()
 
void doSeekClick ()
 
 ISR (PCINT2_vect)
 
void setup ()
 --— Main functions setup() and loop() --— More...
 
void loop ()
 Constantly look for the things, that have to be done. More...
 

Variables

RADIO_FREQ preset []
 
int i_sidx = 5
 
int i_smax = 14
 
int encoderLastPos
 last received encoder position More...
 
unsigned long encoderLastTime
 last time the encoder or encoder state was changed More...
 
char rdsServiceName [8+2]
 String with the actual RDS Service name. Some senders put rotating text in here too. More...
 
char rdsText [64+2]
 String with the actual RDS text. More...
 
char rdsTime [6]
 String with the actual time from RDS as hh:mm. More...
 
SI4705 radio
 
unsigned long nextFreqTime = 0
 next time for lcd update the frequency. More...
 
unsigned long nextRadioInfoTime = 0
 next time for lcd update the radio information More...
 
RDSParser rds
 get a RDS parser More...
 
RADIO_STATE state
 The state variable is used for parsing input characters. More...
 
RADIO_STATE rot_state
 
 WEBSERVER_OFF
 
 WEBSERVER_IDLE
 
 PROCESS_GET
 
 PROCESS_PUT
 
 PROCESS_POST
 
 PROCESS_ERR
 
 PROCESS_STOP
 
byte mac [] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }
 
char * CONTENTTYPES
 
EthernetClient _client
 
WebServerState webstate
 
char _readBuffer [BUFSIZ]
 a buffer that is used to read a line from the request header and for reading file content. More...
 
char _writeBuffer [BUFSIZ]
 a buffer that is used to compose a line for the reponse. More...
 
char _httpVerb [6]
 
char _httpURI [40]
 
int _httpContentLen
 

Detailed Description

Radio implementation using a web frontend served by the Arduino.

Author
Matthias Hertel, http://www.mathertel.de

This is a full function radio implementation ...
The web site is stored on the SD card. You can find the web content I used in the web folder.
It can be used with various chips after adjusting the radio object definition.

Wiring

The hardware setup for this sketch is: Arduino MEGA board with Ethernet shield on top. Arduino UNO has not enough memory. A 2*16 LCD Display in the I2C bus using a PCF8574 board with address 0x27. A Rotary encoder with the data pins on A8 and A9. A Rotary encoder press function on pin A10. A button for scanning upwards on pin A11.

Macro Definition Documentation

#define BUFSIZ   256
#define CR   '\r'
#define CRLF   F("\r\n")
#define DEBUGFUNC0 (   fn)    { Serial.print('>'); Serial.print(fn); Serial.println("()"); }
#define DEBUGFUNC1 (   fn,
 
)    { Serial.print('>'); Serial.print(fn); Serial.print('('); Serial.print(v); Serial.println(')');}
#define DEBUGIP (   l,
 
)    { Serial.print('>'); Serial.print(l); Ethernet.n().printTo(Serial); Serial.println(); }
#define DEBUGTEXT (   txt)    { Serial.print('>'); Serial.println(txt); }
#define DEBUGVAR (   l,
 
)    { Serial.print('>'); Serial.print(l); Serial.print(": "); Serial.println(v); }
#define ENCODER_FALLBACK   (3*1000)

after 3 seconds no turning fall back to tune mode.

ChangeLog:

  • 06.11.2014 created.
  • 22.11.2014 working.
  • 07.02.2015 more complete implementation
  • 14.02.2015 works with no ethernet available (start radio first then Internet but slow).
  • 17.04.2015 Return JSON format.
  • 01.05.2015 faster WebServer responses by using a buffer.
  • 16.05.2015 Using StringBuffer to collect output at several places for reducing net packages.
#define HTML_CLOSE   F("</body></html>")
#define HTML_OPEN   "<html><head></head><body>"
#define HTTP_200   F("HTTP/1.1 200 OK\r\n")
#define HTTP_200_CT   F("HTTP/1.1 200 OK\r\nContent-Type: ")
#define HTTP_CT   F("Content-Type: ")
#define HTTP_ENDHEAD   CRLF
#define HTTP_GENERAL   F("Server: Arduino\r\nConnection: close\r\n")
#define HTTP_NOCACHE   F("Cache-Control: no-cache\r\n")
#define HTTPERR_404   F("HTTP/1.1 404 Not Found\r\n")
#define LF   '\n'
#define NUL   '\0'
#define REDIRECT_FNAME   "/redirect.htm"

The filename on the disk that is used when requesting the root of the web.

#define SPACE   ' '

Enumeration Type Documentation

State definition for this radio implementation.

Enumerator
STATE_PARSECOMMAND 

waiting for a new command character.

STATE_PARSEINT 

waiting for digits for the parameter.

STATE_EXEC 

executing the command.

STATE_NONE 
STATE_PARSECOMMAND 

waiting for a new command character.

STATE_PARSEINT 

waiting for digits for the parameter.

STATE_EXEC 

executing the command.

STATE_FREQ 
STATE_VOL 
STATE_MONO 
STATE_SMUTE 
STATE_PARSECOMMAND 

waiting for a new command character.

STATE_PARSEINT 

waiting for digits for the parameter.

STATE_EXEC 

executing the command.

STATE_NONE 
STATE_PARSECOMMAND 

waiting for a new command character.

STATE_PARSEINT 

waiting for digits for the parameter.

STATE_EXEC 

executing the command.

STATE_FREQ 
STATE_VOL 
STATE_MONO 
STATE_SMUTE 

Function Documentation

enum WebServerState __attribute__ ( (packed)  )
char* _ctCopyWord ( char *  text,
char *  word,
int  len 
)
char* _ctFind ( char *  table,
char *  key 
)

–— Web Server interface –—

This is a helper function that finds the entry for a given key in a table that is formatted in multiple text lines separated by
. Each line starts with a key word and a SPACE character. The pointer to the rest of the line is returned or null.

char* _ctNextWord ( char *  text)

This is a helper function that returns the position to the next word on the same line. This is done by skipping all non-SPACE characters and then all SPACE characters and returns this position.

void DisplayFrequency ( )

–— LCD functions –—

Update the Frequency on the LCD display.

void DisplayMono ( uint8_t  v)

Display the current mono switch.

void DisplayServiceName ( char *  name)

This function will be called by the RDS module when a rds service name was received. The text be displayed on the LCD and written to the serial port and will be stored for the web interface.

void DisplaySoftMute ( uint8_t  v)

Display the current soft mute switch.

void DisplayText ( char *  text)

This function will be called by the RDS module when a rds text message was received. The text will not displayed on the LCD but written to the serial port and will be stored for the web interface.

void DisplayTime ( uint8_t  hour,
uint8_t  minute 
)

This function will be called by the RDS module when a rds time message was received. The time will not displayed on the LCD but written to the serial port.

void DisplayVolume ( uint8_t  v)

Display the current volume. This function is called after a new volume level is choosen. The new volume is displayed on the LCD 2. Line.

void doMenuClick ( )
void doSeekClick ( )
RotaryEncoder encoder ( A9  ,
A8   
)

Setup the RotaryEncoder.

ISR ( PCINT2_vect  )
LiquidCrystal_PCF8574 lcd ( 0x27  )

get a LCD instance

The lcd object has to be defined by using a LCD library that supports the standard functions When using a I2C->LCD library ??? the I2C bus can be used to control then radio chip and the lcd.

void loop ( )

Constantly look for the things, that have to be done.

Look for incomming webserver requests and answer them...

Check for changed signals on the buttons and rotary encoder.

Check for serial input commands and trigger command execution.

Check for new radio data.

Check for new LCD data to be displayed.

void loopButtons ( unsigned long  now)

–— Rotary encoder and buttons –—

Constantly check for changed signals on the buttons and rotary encoder.

void loopLCD ( unsigned long  now)

Constantly check for new LCD data to be displayed.

void loopRadio ( unsigned long  now)

Check once new radio data.

void loopSerial ( unsigned long  now)

setupSerial

Constantly check for serial input commands and trigger command execution.

void loopWebServer ( unsigned long  now)

This is the main webserver routine. Constantly look for incomming webserver requests and answer them...

OneButton menuButton ( A10  ,
true   
)

Setup a Menu Button.

void RDS_process ( uint16_t  block1,
uint16_t  block2,
uint16_t  block3,
uint16_t  block4 
)
void readRequestLine ( )

Read one line of text from _client into the _readBuffer.

void respond404NotFound ( )
void respondEmptyFile ( )
void respondFileContent ( char *  fName)

Responds the content of a file from the SD disk given by fName.

void respondFileList ( )
void respondRadioData ( )

Response to a $info request and return all information of the current radio operation. Format al data as in JSON Format.

void respondSystemInfo ( )
void runRadioJSONCommand ( char *  cmd,
int16_t  value 
)

--— forwards --—

Execute a command identified by a character and an optional number. See the "?" command for available commands.

Parameters
cmdThe command word.
valueAn optional parameter for the command.
void runRadioSerialCommand ( char  cmd,
int16_t  value 
)

interpret a command for the radio chip used on the Serial input. It's a single char command and an optional numeric value. See help output on the '?' command for syntax.

OneButton seekButton ( A11  ,
true   
)

Setup a seek button.

EthernetServer server ( 80  )
void setup ( )

--— Main functions setup() and loop() --—

void setupLCD ( )

Setup the LCD display.

void setupRadio ( )

Setup a FM only radio configuration with I/O for commands and debugging on the Serial port.

Variable Documentation

EthernetClient _client
int _httpContentLen
char _httpURI[40]
char _httpVerb[6]
char _readBuffer[BUFSIZ]

a buffer that is used to read a line from the request header and for reading file content.

char _writeBuffer[BUFSIZ]

a buffer that is used to compose a line for the reponse.

char* CONTENTTYPES
Initial value:
=
"htm text/html 1\n"
"css text/css 1\n"
"js application/x-javascript 1\n"
"txt text/txt 0\n"
"png image/png C\n"
"gif image/gif C\n"
"jpg image/jpeg 1\n"
"ico image/x-icon 1"
int encoderLastPos

last received encoder position

unsigned long encoderLastTime

last time the encoder or encoder state was changed

int i_sidx = 5
int i_smax = 14
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }
unsigned long nextFreqTime = 0

next time for lcd update the frequency.

unsigned long nextRadioInfoTime = 0

next time for lcd update the radio information

RADIO_FREQ preset[]
Initial value:
= {
8770,
8810,
8820,
8850,
8890,
8930,
8980,
9180,
9220, 9350,
9440,
9510,
9530,
9560,
9680, 9880,
10020,
10090,
10110,
10030, 10260, 10380, 10400,
10500
}
PROCESS_ERR
PROCESS_GET
PROCESS_POST
PROCESS_PUT
PROCESS_STOP
SI4705 radio

The radio object has to be defined by using the class corresponding to the used chip. by uncommenting the right (one only) radio object definition.

RDSParser rds

get a RDS parser

char rdsServiceName[8+2]

String with the actual RDS Service name. Some senders put rotating text in here too.

char rdsText[64+2]

String with the actual RDS text.

char rdsTime[6]

String with the actual time from RDS as hh:mm.

RADIO_STATE rot_state
RADIO_STATE state

The state variable is used for parsing input characters.

WEBSERVER_IDLE
WEBSERVER_OFF
WebServerState webstate