Saturday, February 28, 2015

PDC1211: a 7 segments LCD




Abstract
The PDC1211 is a 7-segments display LCD. In this post we provide a library for dealing with this display. The library is strongly inspired by the classical LiquidCrystal library.

Main Characteristics
Module size (WxH):
95.6 x 32.6 mm
Active area (W x H):
77.4 x 16.8 mm
Viewing angle:
6:00
Driving voltage:
5V
Driving IC:
HT1621
Operating temp.:
-2O°C to 60°C
Storage temp.:
-30°C to 70°C
Manifacturer:
Nanjing Guoxian Electronics Corp

Figure 1. PDC1211: special symbols and pinout.


Introduction
The PDC1211 is a 7 segments LCD which is (was?) used mainly for telephony purposes. It has 12 7-segments digits and 7 special symbols. Figure 1 provides an overall view of the display and the position of the special symbols (numbered 1 to 7 in red). Indeed, more than symbols these seems to be sentences written in Chinese. Since I don't know Chinese, I have no idea of their meaning. Except for the 4th one which I got translated from a Chineese girl that I met in the train: "Local phone (number)". I would be grateful to any of you that could provide a translation for the remaining symbols/sentences.

Encoding a character
Concerning the representation of the digits, the PDC1211 follows the requirements of the HT1211 chip. Figure 2 shows the wiring of the backpane and Figure 3 the wiring of the frontpane. These are useful to compute the code values for the printable characters.


Figure 2. Wiring of the backpane.
Figure 3. Wiring of the frontpne.

Segment 0 of the memory mapping of the HT1621 corresponds to the leftmost digit. As illustrated in Figure 3, two memory segment adresses are used to encode a single character. Segments named a, b, c, d are the least significant bits and e, f, g, h. So to encode a 0 for example, one would set segments b, c, d in the first address and e, f, h in the other. Hence we obtain 0xE (or 0B1110) for the first segment and 0xB for the second. However, it is not recommended to write directly these values to the HT1621 but pass either through the write function or through the standard Print interface (see the dedicated section).

Configuration
Libraries. In order to work this library needs the following libraries installed: both of them can be downloaded from this website.
Pinout. The pins on the module are numbered 1 (leftmost) to 5 (rightmost) and are associated as in Figure 1 where SS is pin 1 and Vcc is the number 5. In our examples, pin 1 is connected to Arduino pin 2, pin 2 to Arduino pin 3 and pin 3 to Arduino pin 4.

Installing the library
As all Arduino's additional libraries, PDC1211 has to be installed in your local Arduino's library directory (look into Preference pane of your Arduino IDE to discover the path) in a directory called PDC1211/src. The documentation can be installed into PDC1211/doc.

Communication protocol
The communication between Arduino and the PDC1211 follows the same protocol as for the HT1621 but here Read/Write signals are on the same pin (RW) (see the documentation here for more details).

The print interface
This library implements the method of the Print interface of LiquidCrystal with all its advantages and all of its drawbacks. Moreover, remark that the type of the value to print is important, for example the following instructions all have the same effect of printing a '0' symbol on the LCD

lcd.print((char)0xBE);
lcd.print('0');
lcd.print("0");

while the following

lcd.print(0xBE);

will print a three character string "190" ie. the integer value of 0xBE.
Finally, since this is a 7 segments display and hence not all characters can be displayed. The set of displayable characters is reduced to: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, b, C, c, d, E, F, H, h, L, N, n, o, P, r, t, U, u, -, . and space.

The examples
The following snippet shows the typical usage of the library

// mandatory include files
#include "HT1621.h"
#include "LiquidCrystal7S.h"
#include "PDC1211.h"
// Pin connections 
#define SS 2
#define RW 3
#define DATA 4
// LCD class instantiation
PDC1211 lcd(SS,RW,DATA);

void setup() { ... lcd.begin(); ... }

void loop() { ... lcd.print("HELLO"); // print something ... }

All the examples shipped with LiquidCrystal library run as well exception made, of course, for those implying unsupported methods (see section next section).

Supported LiquidCrystal methods
Since PDC1211 is a child class of the LiquidCrystal7S class, it supports all of the methods of this class. However, they are a subset of those implemented by the LiquidCrystal library since they are impossible to implement in the context of a 7 segments display. Here is the full list of the unsupported methods:
  • cursor()
  • noCursor()
  • blink()
  • noBlink()
  • createChar()
  • blink()
  • noBlink()
  • createChar()

Downloads
The library consists in only one header and an implementation files:
And here it is the documentation both in pdf and html (zipped) formats:

Enjoy!

Sunday, February 1, 2015

FM radio receiver for your Arduino (TEA5767/TEA5768/TEA5757)
(Part 4/4)




Abstract

In this last part we provide a basic front-end for the FM radio and a simple example program. Moreover, we provide full documentation for all the TEA library and their classes.

This project is a simple implementation of a FM Radio player based on the FM module. The radio has a simple front-end consisting of the LCD module and its buttons. The are five possible working modes. For more details on the working modes see the Section "Using the radio".

Building the radio

Just stack the LCD module (more infos here) on your Arduino and connect the FM module as explained here. That's all!

Display and buttons

In all working modes (except for the sub-modes) the information is displayed in a standard format on the LCD. The first line indicates the frequency of the current station being reproduced (approx to 2 decimal digits) and the current working mode. The second line displays the audio level (a number between 0 and 16) and if the reception is stereo or mono. The following figure gives a more visual illustration of the display organisation.
Figure 1. Display organisation in main working modes.

The radio uses 4 out the 5 buttons on the LCD module (the leftmost ones). The leftmost button (button 1) and the its neighbor (button 2) are used as navigation buttons. In standard mode (STD), they are used to search backward (resp. forward) for the next station to reproduce. In recording mode (REC) and in memory mode (MEM), they are used to move backward or forward in the memory array. Button 3 is called mode button and it is used to change the working mode. Button 4 is called action button and it is used to confirm actions for the current working mode. For example, when choosing a memory slot for memorizing the current station in the memory array, if this button is pressed then the frequency of the current station is recorded and the radio returns in STD mode. The following figure illustrates buttons positions.
Figure 2. Buttons of the LCD module.

Warning For lack of space when displaying information on the LCD, some shortcuts are used. For example, btn means "button" and act means "action", etc.

Using the radio

At power on time, the radio is tuned at frequence 87.5 MHz on the US/European FM band, if a station is present then the radio starts reproducing it, otherwise noise is heard. Standard mode (STD) is activated. All entries of the memory array are initialized at 87.5MHz. The backward and forward buttons can be used to select other stations in the band. The search for the next station wraps around the band limits.

Using the mode button, the working mode can be changed. The radio has five operating modes:
  • standard (STD): we just described this.
  • recording (REC): in this mode the user can save the current frequency to memory. The user is prompted to choose a slot in the memory in which to store the frequency of the current station. Once the slot number is chosen, press the action button to confirm selection. Use the forward/backward buttons to navigate in the memory array.
  • memory (MEM): reproduces the station memorized at current position in the memory array. Use the forward/ backward buttons to navigate in the memory array.
  • preselect (PRE): this mode automatically preselects the stations with better reception level (SEARCH_LEV_MEDIUM) and memorize them into the memory array. The scan is started from the current frequency toward the superior band limit and restarts from the inferior band limit if the memory has not been completely filled. The filling of the memory follows a greedy policy. The scan is stopped if after two successive trials no station is found.
  • standby (SBY): sets the radio in standby. Press action button to return in STD mode.

Configuration and fine tuning

Configuring the front-end. The radio class has been kept as simple as possible. In this way its configuration is very simple. All you need to edit it is the file FM_Radio_Config.h and update information about the pins used by the LCD module. You need also to specify the size of the memory array (constant MEMOMAX) that will be used by the radio to store the frequency of your preferred radio stations.

Configuring the FM module. The radio is configured to work with EU/US band limits. If you want to change japanese band limits, then you have to replace EUROPEAN_FM_BAND by JAPANESE_FM_BAND in function TEA576X::begin(). Please check also the working parameters of your FM module (crystal frequency, etc) and configure them accordingly. Remark also that high side injection is selected by default.

Delays. In the reading and write operations (immediately after them) it is often used a delay to allow the operation to finish. The delays are sometimes overestimated to be sure to work with most modules. Maybe the user can change them to adapt more closely to his module and increase the overall performances.

Also in the front-end (FM_Radio.cpp) a number of delays are set. Also those can be change to improve performance or user experience.

Test sketch

The simplicity of the design allows to run our radio with a very simple sketch.

#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#include "FM_Radio.h"
FM_Radio radio;
void setup() {
  radio.begin(LCD_BTN, MEMOMAX);
}
void loop() {
  radio.loop();
}

Documentation

You may download the full documentation about all classes in this article series in the following formats:

See also

Friday, January 30, 2015

A spinning top for your LCD





Sometimes we need to wait for the end of a task or for an event to occur and at the same time to keep the user informed that the system is not hung. This is the right occasion for a spinning top!

In this post we propose a very simple one. Indeed, it is a good occasion to see how to use the character generator of the LCD and insert new character. The module that we are going to use is based on the famous Hitachi HD44780 chip. This chip has the possibility to increase its char set with 4 additional user defined chars. This easily done using the command createChar which take in input the id code for the new char (an integer between 0 and 3) and an array of 8 bytes which are interpreted as a bitmap (here we use the 5x8 charset).

What you need
  • 1x Arduino Uno
  • 1x LCD module
Just that! For more on the LCD module you can also have a look here.

Configuration
Modify the definitions of the pins to adapt to your LCD module. In order to change the speed of the spinner decrease the value of FRAMETIME. This variable control the frame rate. Indeed, frame rate is approx 1/FRAMETIME.

The sketch
/**
 * Spinning top
 *
 * \author Enrico Formenti
 * \version 1.0
 * \date 30 january 2015
 *  \copyright BSD license, check the License page on the blog for more information. All this text must be 
 *  included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include <LiquidCrystal.h>

// modify the definitions below according to your LCD module
 
#define LCD_RS_PIN 7
#define LCD_ENABLE_PIN 6
#define LCD_DATA4_PIN 5
#define LCD_DATA5_PIN 4
#define LCD_DATA6_PIN 3
#define LCD_DATA7_PIN 2

LiquidCrystal lcd(LCD_RS_PIN, LCD_ENABLE_PIN, LCD_DATA4_PIN,
                  LCD_DATA5_PIN, LCD_DATA6_PIN, LCD_DATA7_PIN);


// modify the value below to change the frame rate
// framerate per second is approx 1/FRAMETIME 
#define FRAMETIME 120


// the backslash character is not in the standard char set
// of the LCD so let's redefine it

uint8_t backslash[8] = {
    0b00000,
    0b10000,
    0b01000,
    0b00100,
    0b00010,
    0b00001,
    0b00000,
    0b00000
};

// we use special character 0 here
char spinningTop[] = {'/', '-', 0, '|'};
uint8_t k;

void setup() {
  // put your setup code here, to run once:
  k = 0; // init spinner
  
  // init screen
  lcd.begin(16, 2);
  lcd.createChar(0, backslash);
  lcd.clear();
  lcd.print("Look at me... ");
}

void loop() {
  // update spinner and...
  lcd.setCursor(14,0);
  lcd.write(spinningTop[k%4]);
  k = (k+1) & 0b11;
  // ...waste some time to let user see it spinning
  delay(FRAMETIME);
}

Suggestions
Remark that our implementation of the spinner uses busy waiting. In order to avoid it one can use interrupts. However, if you decide to use interrupts, recall that they can interfere with other modules or sensors and that Arduino Uno only has two of them!

Enjoy!

Sunday, January 11, 2015

FM radio receiver for your Arduino (TEA5767/TEA5768/TEA5757)
(Part 3/4)




Abstract

In this third part we provide a class for the FM module and a simple test program. The next post will provide a basic FM Radio front-end as an application of the FM module.

The FM module
As we have already said in past posts, this is a decoration module for a module based on the TEA5767HN chip. In particular, it fixes some important parameters such as the clock and the bus. Here are the main characteristics of the module:
Main characteristics
 
Supply voltage:
3V-6V
Working current:
25mA
Audio output:
2x10mW
Clock:
32768Hz
Bus:
I2C
I2C address:
0x60

We have therefore conceived a wrap class which hides all the details about TEA5767HN, sets up the above constraints and provides few basic methods for the final user. Please look into the code below for the methods and for documentation. The pinout of the module is given here.


We start with the file FM_Module.h:
/**
 *  \file FM_Module.h
 *
 *  \brief A class for the FM module based on the TEA5767HN chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \version 1.0
 *  \copyright BSD license, check the License page on the blog for more information. All this text must be
 *  included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#ifndef ____FM_Module__h
#define ____FM_Module__h

#include "TEA5767HN.h"

/**
 * \class FM_Module
 * \brief A class for the FM module based on the TEA5767HN chip.
 * \details This is a simple class for a FM module based on the TEA5767HN chip. The class implements
 * faithfully the module functioning. Moreover, it provides some basic commands for FM radio playing.
*/

class FM_Module {
    /**
     * \var TEA5767HN FM
     * \brief This is the internal FM receiver which pratically does all the job.
     * \see TEA5767HN
     */
    TEA5767HN FM;
    /**
     * \var bool standby
     * \brief Flag for signalling if the standby is enabled. This is a quick trick to avoid unuseful call to the TEA5767HN module.
     */
    bool _standby;
public:
    /**
     * \fn void begin()
     * \brief Initialize the FM module. This command has always to be issued before using the module.
     */
    void begin();
    /**
     * \fn void setFrequency(float f)
     * \brief Set the frequency of the FM receiver.
     * @param float f The desired frequency in MHz.
     * \see getFrequency()
     */
    inline void setFrequency(float f) { FM.setFrequency(f); };
    /**
     * \fn float getFrequency()
     * \brief Returns the frequency on which the receiver is tuned
     * \return Returns the frequency in MHz on which the tuner is tuned.
     */
    inline float getFrequency() { return FM.getFrequency(); };
    /**
     * \fn bool searchForward()
     * \brief Search for a station in the direction of the superior band limit. 
     * \return \c true if the search is successful, \c false otherwise.
     * \see searchBackward()
     *
     * Search for a station in the direction of the superior band limit. If the superior band limit is reached, then the search restarts from the inferior band limit.
     * The search is abandoned after one complete loop.
     */
    inline bool searchForward() { return FM.search(SEARCH_DIR_FORWARD, SEARCH_LEV_MEDIUM); };
    /**
     * \fn bool searchBackward()
     * \brief Search for a station in the direction of the inferior band limit.
     * \return \c true if the search is successful, \c false otherwise.
     * \see searchForward()
     *
     * Search for a station in the direction of the inferior band limit. If the inferior band limit is reached, then the search restarts from the superior band limit.
     * The search is abandoned after one complete loop.
     */
    inline bool searchBackward() { return FM.search(SEARCH_DIR_BACKWARD, SEARCH_LEV_MEDIUM); };
    /**
     * \fn void refresh()
     * \brief Refreshes the internal state of the FM module.
     *
     * Refreshes the internal state of the FM module. This is particularly useful before issuing commands like isStereo() or getLevel()
     */
    inline void refresh() { FM.read(); }
    /**
     * \fn void standby()
     * \brief Put the FM module in standby state
     */
    inline void standby() { if(!_standby){_standby = true; FM.standby(STANDBY_ON); FM.write();}};
    /**
     * \fn void play()
     * \brief The tuner is set into play state.
     */
    inline void play() { if(_standby) {FM.standby(STANDBY_OFF); FM.write(); _standby=false;}};
    /**
     * \fn bool isStereo()
     * \brief This function queries for the current quality of the reproduction: stereo or mono.
     * \return \c true if the reproduction is stereo, \c false if it is mono.
     * \see refresh()
     * \warning It is better to issue a \c refresh() command before calling this function in order to have fresh informations from the receiver.
     */
    inline bool isStereo(){ return FM.isStereo(); };
    /**
     * \fn uint8_t getLevel()
     * \brief This function returns the output level of the receiver.
     * \return An integer between 0 and 15 indicating the output level of the receiver.
     * \see refresh()
     * \warning It is better to issue a \c refresh() command before calling this function in order to have fresh informations from the receiver.
     */
    inline uint8_t getLevel() { return FM.getLevel(); };
};


#endif /* defined(____FM_Module__h) */


Here is the file FM_Module.cpp:
/**
 *  \file FM_Module.cpp
 *
 *  \brief Implementation of a class for the FM module based on the TEA5767HN chip.
 *
 *  \author Enrico Formenti
 *  \date 18 dec 2014
 *  \version 1.0
 *  \copyright BSD license, check the License page on the blog for more information. All this text must be
 *  included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include "FM_Module.h"

void FM_Module::begin() {
    Wire.begin();               // Init I2C bus
    FM.begin(TEA576X_XTAL_32768Hz, TEA5767HN_I2CBUS); // Init TEA receiver
    _standby = false;
}

And finally a very basic test sketch :-)
#include <Wire.h>
#include <SPI.h>
#include "FM_Module.h"
#include "TEA5767HL.h"

FM_Module mod;
TEA5767HL tea;

void setup() {

  mod.begin();

  mod.searchForward();
  
  mod.play();
}

void loop() {
  // listening to Radio don't care here ;-)

}


What's next

As promised in the last post of this series we will see a basic FM Radio front-end with LCD support.

See also

Wednesday, December 31, 2014

FM radio receiver for your Arduino (TEA5767/TEA5768/TEA5757)
(Part 2/4)





Abstract

In this second part we provide C++ classes to deal with TEA576X family of chips. We also provide a basic sketch for using the TEA5767HN module that one may buy for few bucks. The next post will be concerned with the FM module and the last one will provide an example of (basic) FM Radio as an application of the FM module.


Updated

After further tests some bugs were found. Here is the list:
  • Read procedures in TEA5767HN.cpp and TEA5768HL.cpp
  • #define constants in TEA576X.h
  • Search procedure in TEA576X.cpp
Please download all those files again!



TEA576X
Recall that the chips of the family TEA576X differ only for the communication protocol (SPI or I2C). We have therefore conceived an abstract class, TEA576X, which implements all the methods except the write and read functions that are delegated to the derived classes. Both the header and the implementation files are pretty long, you can download them below:

The headers
Choose the header you need for your sketches. Save these files as ClassName.h

Class TEA5767HL
/**
 *  \file TEA5767HL.h
 *
 *  \brief A class for dealing with TEA5767HL chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \version 1.0
 *
 *  \copyright BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#ifndef ____TEA5767HL__
#define ____TEA5767HL__

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif


#include "TEA576X.h"
#include <SPI.h>

#define M_FM_TEA5767HL 0xC8189CB3

/**
 \class TEA5767HL TEA5767HL.h
 \brief A class for TEA5767HL component.
 
 This class implements the methods to interact with the TEA5767HL component
 which is a FM receiver. For more on this component refer to
 http://macduino.blogspot.com/2014/12/FM-Radio-TEA5767.html
 
 \see TEA576X
 */

class TEA5767HL : public TEA576X {
private:
    /**
     * \var _SSPin
     * \brief Slave Select pin for the SPI protocol.
     */
    uint8_t _SSPin; // Slave Select pin
public:
    /**
        \fn void begin(float xtal, uint8_t SSpin)
        \brief Init TEA5767HL chip.
        @param SSpin Slave Select pin.
    */
    void begin(float xtal, uint8_t SSpin);
    /**
     \fn void write()
     \brief Send the current write sequence to the TEA5767HL.
     \warning All the operations or changes to the module settings have no effect
     untill a write() operation is issued.
     */
    void write();
    /**
     \fn void read()
     \brief Read-in the current read sequence of the TEA5767HL.
     */
    void read();
};


#endif /* defined(____TEA5767HL__) */
Class TEA5768HL
/**
 *  \file TEA5768HL.h
 *
 *  \brief A class for dealing with TEA5768HL chip.
 *
 *  \author Enrico Formenti,
 *  \date 23 dec 2014
 *  \version 1.0
 *
 *  \copyright BSD license, check the License page on the blog for more information. All this text must be 
 *  included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#ifndef ____TEA5768HL__h
#define ____TEA5768HL__h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "TEA576X.h"
#include <Wire.h>

#define M_FM_TEA5767HL 0x717D6A52

/**
 \class TEA5768HL TEA5768HL.h
 \brief A class for TEA5768HL component.
 
 This class implements the methods to interact with the TEA5768HL component
 which is a FM receiver. For more on this component refer to
 http://macduino.blogspot.com/2014/12/FM-Radio-TEA5767.html
 
 \see TEA576X
 */

class TEA5768HL : public TEA576X {
public:
    /**
     \fn void write()
     \brief Send the current write sequence to the TEA5768HL.
     \warning All the operations or changes to the module settings have no effect
     untill a write() operation is issued.
     */
    voidwrite
Class TEA5767HN

Warning: If you have installed Arduino 1.5.8 Beta, then you need to install SPI library manually from GitHub. It can be found here. If you have an older version (1.0.6 for example) then there is no problem since it comes with the SPI library pre-installed.

Implementing the classes
Choose the files you need for your sketches and save the files as ClassName.cpp


Implementation of the class TEA5767HL
/**
 *  \file TEA5767HL.cpp
 *
 *  \brief Implementation of a class for dealing with TEA5767HL chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \version 1.0
 *
 *  \copyright BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include "TEA5767HL.h"

void TEA5767HL::begin(float xtal, uint8_t SSpin) {
    TEA576X::begin(xtal);
    _SSPin = SSpin;
}

void TEA5767HL::write() {
    register uint8_t i;
    
    // take the SS pin low to select the chip:
    digitalWrite(_SSPin,LOW);
    
    // send buffer data
    for(i=0; i<5; i++)
        SPI.transfer(wbuf[i]);

    // take the SS pin high to de-select the chip:
    digitalWrite(_SSPin,HIGH);
}

void TEA5767HL::read() {
    register uint8_t i;
    
    // take the SS pin low to select the chip:
    digitalWrite(_SSPin,LOW);
    
    // read-in buffer data
    for(i=0; i<5; i++)
        rbuf[i] = SPI.transfer(0x0);
    
    // take the SS pin high to de-select the chip:
    digitalWrite(_SSPin,HIGH);
}
Implementation of the class TEA5768HL
/**
 *  \file TEA5768HL.cpp
 *
 *  \brief Implementation of a class for dealing with TEA5768HL chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \date 22 jan 2015
 *  \version 1.1
 *  \copyright BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include "TEA5768HL.h"

void TEA5768HL::write() {
    register uint8_t i;
    
    Wire.beginTransmission(TEA576X_I2C_ADDRESS);
    
    for(i=0; i<5; i++)
        Wire.write(wbuf[i]);
    
    Wire.endTransmission();
}

void TEA5768HL::read() {
    register uint8_t i = 0;
    
    Wire.requestFrom(TEA576X_I2C_ADDRESS, 5);
    
    while(Wire.available())
        rbuf[i++] = Wire.read();
}
Implementation of the class TEA5767HN
/**
 *  \file TEA5767HN.cpp
 *
 *  \brief Implementation of a class for dealing with TEA5767HN chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \date 22 jan 2015
 *  \version 1.1
 *  \copyright BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include "TEA5767HN.h"

void TEA5767HN::begin(float xtal, bool bus, uint8_t SSpin) {
    _bustype = bus;
    _SSPin = SSpin;
    TEA576X::begin(xtal);
}

void TEA5767HN::write() {
    register uint8_t i;
    
    if(_bustype) {
        // take the SS pin low to select the chip:
        digitalWrite(_SSPin,LOW);
    
        // send buffer data
        for(i=0; i<5; i++)
            SPI.transfer(wbuf[i]);

        // take the SS pin high to de-select the chip:
        digitalWrite(_SSPin,HIGH);
    }
    else {
        Wire.beginTransmission(TEA576X_I2C_ADDRESS);
        
        for(i=0; i<5; i++)
            Wire.write(wbuf[i]);
        
        Wire.endTransmission();

    }
}

void TEA5767HN::read() {
    register uint8_t i = 0;

    if(_bustype) {
        // take the SS pin low to select the chip:
        digitalWrite(_SSPin,LOW);
    
        // read-in buffer data
        for(; i<5; i++)
            rbuf[i] = SPI.transfer(0x0);
    
        // take the SS pin high to de-select the chip:
        digitalWrite(_SSPin,HIGH);
    }
    else {
        
        Wire.requestFrom(TEA576X_I2C_ADDRESS, 5);
        
        while(Wire.available())
            rbuf[i++] = Wire.read();
    }
}

The sketch
In order to test the the above classes here is a simple sketch. To run the sketch you need the files TEA5767.* (see above), TEA5767HN.* (see above) and, of course, a TEA5767 FM module (see Figure 2 in this post). The sketch initialises the TEA5767HN and then search for a station. If one is found then the module is tuned at this frequency. Pay attention that by default the tuner uses the US/European FM band (87.5-108MHz), if you need the Japanese FM band (76-91MHz), then you should add the following instruction after tea.begin(...);:
tea.setBandLimits(JAPANESE_FM_BAND);

The sketch TEA5767HN-test.ino
/**
 *  \file TEA5767HN-test.ino
 *
 *  \brief A quick example for testing the TEA5767HN chip.
 *
 *  \author Enrico Formenti
 *  \date 27 dec 2014
 *  \version 1.0
 *  \copyright BSD license, check the License page on the blog for more information. All this text must be 
 *  included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */
 
#include "TEA5767HN.h"

TEA5767HN tea;

void setup() {
  Serial.begin(9600);
  
  tea.begin(TEA576X_XTAL_32768Hz, TEA5767HN_I2CBUS);
  
  if(!tea.search(SEARCH_DIR_FORWARD, SEARCH_LEV_MEDIUM)) {
    Serial.print("Couldn't find any station!");
  }
  else {
    Serial.print("Playing station at ");
    Serial.print(tea.getFrequency()/1000000.0);
    Serial.print("MHz");
  }
}

void loop() {
  // nothing to do at present...
}
To run this sketch you need:
  • 1x Arduino Uno (or one of his brothers)
  • 1x TEA5767HN chip
  • 1x louspeaker 4Ω 1/4 Watt (or similar)
  • 7x Dupont connection cables
  • 1x long enough cable for the antenna (more details here)
Figure 1. shows how to connect the material. Remark that the output level of the module is very weak. This is the reason for which one finds many modules that adds to TEA5767HN an amplification stage, like the one that we will see in the next post.


Figure 1. Basic connections for the TEA5767HN module.



What's next
As promised in the abstract we will provide a class for dealing with the FM module and finally an application example building a simple FM radio player front-end.

See also
FM Radio receiver (TEA5767HL-TEA5767HN-TEA5768HL) - Part 1
FM Radio receiver (TEA5767HL-TEA5767HN-TEA5768HL) - Part 3
FM Radio receiver (TEA5767HL-TEA5767HN-TEA5768HL) - Part 4