Skyduino:~#
Articles
arduino, librairie, programmation, projet

[­Projet Arduino] TrololoFM (base NS73M)

Bonjour tout le monde !

Aujourd’hui je vais vous présenter un petit projet que j’ai réalisé dans un but purement diabolique 🙂

Je vous présente la TrololoFM !

Contrairement à ce que l’on pourrait penser il ne s’agit pas d’une simple trousse mais d’un systéme de rickroll’d contrôlable à distance ]:)

Le hardware est simple, un petit émetteur FM, un module bluetooth, une carte arduino, et un lecteur mp3 avec la musique de rickroll’d en boucle.

Le tout dissimulé astucieusement dans quelque chose de « passe partout ».

Il suffit de poser la TrololoFM à proximité d’une innocente victime (ou d’un groupe d’innocente victime ]:) ) écoutant la radio, de repérer la radio en cours d’écoute et de dégainer un smartphone avec le bluetooth.

Par bluetooth il est alors possible de choisir la fréquence sur laquelle travaille l’émetteur FM et de RickRoll’d quiconque à proximité \o/

Bon plus sérieusement ce projet m’as donné l’occasion de revoir ma librairie pour le module NS73M et de faire quelque chose de plus « propre ».

Voici le code source :

TrololoFM.ino

#include "NS73M_v2.h"
//#include <NS73M.h>

NS73M tuner(12, 11, 10);

/*
HARDWARE PIN CONFIGURATION
 
 NS73M (! 3V3 !) || ARDUINO
 CK -> 10K resistor -> D12
 DA -> 10K resistor -> D11
 
 LA -> 10K resistor -> D10
 
 IIC -> GND Power Rail
 VCC -> 3V3 Power Rail  
 GND -> GND Power Rail
 */

const unsigned int freqTable[] = {
  877, 881, 888, 896, 
  904, 912, 916, 920, 
  926, 933, 940, 944, 
  950, 955, 962, 966, 
  970, 975, 984, 988, 
  994, 1002, 1008, 1012, 
  1016, 1025, 1029, 1043, 
  1047, 1051, 1055, 1059, 
  1064, 1070, 1077 };

char *nameTable[] = {
  "Nostalgie Clermont-Ferrand",
  "Sud radio",
  "Radio FG",
  "Virgin radio Auvergne",
  "France inter",
  "Radio espérance",
  "R.C.F. Puy-de-Déme",
  "RVA",
  "Radio classique",
  "Radio campus Clermont-Ferrand",
  "France maghreb",
  "MFM Radio",
  "Rire et chansons",
  "France musique",
  "Skyrock",
  "Fun radio",
  "Radio altitude",
  "Le Mouv'",
  "France culture",
  "Radio scoop",
  "Jazz radio 2",
  "Radio Arverne",
  "Chérie FM Auvergne",
  "NRJ Clermont",
  "Logos FM",
  "France bleu Pays d'Auvergne",
  "Radio Nova",
  "RTL",
  "Europe 1",
  "RMC",
  "France info",
  "RTL 2",
  "RFM",
  "BFM Business",
  "Autoroute info" };

const unsigned char tableLen = 35;

void listeFreq() {
  for(uint8_t i = 0; i < tableLen; i++) {
    Serial.print(i, DEC);
    Serial.print(" - ");
    Serial.println(nameTable[i]);
  }
}

void setup(){
  Serial.begin(115200);
  Serial.println("- Trololo FM -");
  Serial.println("- FUFUFU FM Broadcast Hooker -");
  tuner.setup(97300000);
  Serial.println();
  listeFreq();
}

void loop(){
  while(Serial.available() < 3);
  char c1 = Serial.read();
  char c2 = Serial.read();
  Serial.read(); // newline
  
  if(c1 == '?') {
    Serial.println();
    listeFreq();
  } else {
    c2 -= 48;
    c2 += (c1 - 48) * 10;
    if(c2 > tableLen || c2 < 0 ) return;
    Serial.print("Tunning to ... ");
    Serial.print(nameTable[c2]);
    Serial.print(" at ");
    Serial.print(freqTable[c2] / 10, DEC);
    Serial.println(" MHz.");
    tuner.tune(freqTable[c2] * 100000, true);
  }
  Serial.flush();
}

NS73M_v2.h

/*
 * NS73M Library by SkyWodd @ 2011
 * Based on SPI function by Cai Maver
 * And Frequency Calcul by Cai Maver 
 */

#ifndef NS73M_H_
#define NS73M_H_

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

/*
HARDWARE PIN CONFIGURATION
 
 NS73M (! 3V3 !) || ARDUINO
 CK -> 10K resistor -> Digital 12 || User Custom
 DA -> 10K resistor -> Digital 11 || User Custom
 
 LA -> 10K resistor -> Digital 10 || User Custom
 
 IIC -> GND Power Rail
 VCC -> 3V3 Power Rail
 GND -> GND Power Rail
 */

#define REG0 0x00
#define REG1 0x01
#define REG2 0x02
#define REG3 0x03
#define REG4 0x04
#define REG6 0x06
#define REG8 0x08
#define REG14 0x0E

// REG0 ----------------------------------
// Power SW
#define PW_MASK 1
#define PW_ON 1
#define PW_OFF 0

// Crystal SW
#define PDX_MASK 2
#define PDX_ON 0
#define PDX_OFF 2

// Mute SW
#define MUTE_MASK 4
#define MUTE 4
#define UNMUTE 0 

// Pre-emphasis SW
#define PE_MASK 16
#define PE_ON 0
#define PE_OFF 16

// Pre-emphasis selection
#define EMS_MASK 32
#define EMS_50 0 // Europe
#define EMS_75 32 // USA

// Audio input level
#define INPUT_MASK 192
#define INPUT_LOW 0
#define INPUT_MEDIUM 64
#define INPUT_HIGH 128

// REG1 ----------------------------------
// Pilot tune
#define PLT_MASK 8
#define PLT_ON 0
#define PLT_OFF 8

// Force subcarrier
#define SUBC_MASK 64
#define SUBC_ON 0
#define SUBC_OFF 64

// REG2 ----------------------------------
// Tx power level
#define POWER_MASK 3
#define POWER_LOW 1
#define POWER_MEDIUM 2
#define POWER_HIGH 3

// Locked Detect
#define ULD_MASK 4
#define ULD_ON 4
#define ULD_OFF 0

// REG6 ----------------------------------
// Charge pumps
#define CIA_MASK 30
#define CIA_1_25 2
#define CIA_80 6
#define CIB_320 24

// REG8 ----------------------------------
// Frequency band
#define BAND_MASK 3
#define BAND_0 0
#define BAND_1 1
#define BAND_2 2
#define BAND_3 3

#define uint8_t byte 
#undef abs
#undef round

class NS73M {
public:
  NS73M(void);
  NS73M(int _CK, int _DA, int _LA);
  void power(uint8_t mode);
  void crystal(uint8_t mode);
  void mute(uint8_t mode);
  void preEmphasis(uint8_t mode);
  void preEmphasisLevel(uint8_t mode);
  void soundLevel(uint8_t mode);
  void piloteTone(uint8_t mode);
  void forcedSubCarrier(uint8_t mode);
  void powerLevel(uint8_t mode);
  void unlockDetect(uint8_t mode);
  void tune(unsigned long frequency, uint8_t doReset = true);
  void chargePumps(uint8_t mode);
  void softReset(void);
  void regReset(void);
  void setup(unsigned long frequency);
  //void debug();
private:	
  uint8_t CK;  //clock pin
  uint8_t DA;  //data pin
  uint8_t LA;  //latch pin
  uint8_t R0;
  uint8_t R1;
  uint8_t R2;
  uint8_t R3;
  uint8_t R4;
  uint8_t R6;
  uint8_t R8;
  void selectBand(uint8_t mode);
  void spiSend(uint8_t reg, uint8_t data);
};

#endif // NS73M_H_

NS73M_v2.cpp

#include "NS73M_v2.h"
#define setReg(reg, mask, value) reg = (reg & ~mask) | value

NS73M::NS73M(void)
{
  NS73M(12, 11, 10);
}

NS73M::NS73M(int _CK, int _DA, int _LA)
{
  CK = _CK;
  DA = _DA;
  LA = _LA;

  pinMode(CK, OUTPUT);
  pinMode(DA, OUTPUT);
  pinMode(LA, OUTPUT);

  digitalWrite(LA, LOW);

  regReset();	
}

/* REGISTER 0 */
void NS73M::power(uint8_t mode)
{
  setReg(R0, PW_MASK, mode);
  spiSend(REG0, R0);
}

void NS73M::crystal(uint8_t mode)
{
  setReg(R0, PDX_MASK, mode);
  spiSend(REG0, R0);
}

void NS73M::mute(uint8_t mode)
{
  setReg(R0, MUTE_MASK, mode);
  spiSend(REG0, R0);
}

void NS73M::preEmphasis(uint8_t mode)
{
  setReg(R0, PE_MASK, mode);
  spiSend(REG0, R0);
}

void NS73M::preEmphasisLevel(uint8_t mode)
{
  setReg(R0, EMS_MASK, mode);
  spiSend(REG0, R0);
}

void NS73M::soundLevel(uint8_t mode)
{
  setReg(R0, INPUT_MASK, mode);
  spiSend(REG0, R0);
}

/* REGISTER 1 */
void NS73M::piloteTone(uint8_t mode)
{
  setReg(R1, PLT_MASK, mode);
  spiSend(REG1, R1);
}

void NS73M::forcedSubCarrier(uint8_t mode)
{
  setReg(R1, SUBC_MASK, mode);
  spiSend(REG1, R1);
}

/* REGISTER 2 */
void NS73M::powerLevel(uint8_t mode)
{
  setReg(R2, POWER_MASK, mode);
  spiSend(REG2, R2);
}

void NS73M::unlockDetect(uint8_t mode)
{
  setReg(R2, ULD_MASK, mode);
  spiSend(REG2, R2);
}

/* REGISTER 3 & 4 */
void NS73M::tune(unsigned long frequency, uint8_t DoReset)
{
  if (frequency < 88500000) {                       // Band 3
    selectBand(BAND_3);
  }
  else if (frequency < 97900000) {                  // Band 2
    selectBand(BAND_2);
  }
  else if (frequency < 103000000) {                  // Band 1 
    selectBand(BAND_1);
  }
  else{
    // Must be OVER 103.000.000,                    // Band 0
    selectBand(BAND_0);
  }

  frequency = (frequency + 304000) / 8192;
  R3 = frequency & 255;
  R4 = frequency >> 8;

  spiSend(REG3, R3);
  spiSend(REG4, R4);

  if(DoReset) softReset();
}

/* REGISTER 6 */
void NS73M::chargePumps(uint8_t mode)
{
  setReg(R6, CIA_MASK, mode | CIB_320);
  spiSend(REG6, R6);
}

/* REGISTER 8 */
void NS73M::selectBand(uint8_t mode)
{
  setReg(R8, BAND_MASK, mode);
  spiSend(REG8, R8);
}

/* REGISTER 14 */
void NS73M::softReset(void)
{
  spiSend(REG14, 0x05);
}

/* ALL REGISTER */
void NS73M::regReset(void)
{
  R0 = 0x00;
  R1 = 0xB4;
  R2 = 0x05;
  R3 = 0x8A;
  R4 = 0x2E; // Default 97.4 Mhz
  R6 = 0x1A; // 
  R8 = 0x1B;
}

/* USER FRIENDLY SETUP FUNCTION */
void NS73M::setup(unsigned long frequency)
{
  delay(100);
  regReset();
  softReset();
  forcedSubCarrier(SUBC_ON);
  piloteTone(PLT_ON);
  unlockDetect(ULD_OFF);
  powerLevel(POWER_HIGH);
  tune(frequency, false);
  soundLevel(INPUT_MEDIUM);
  preEmphasis(PE_ON);
  preEmphasisLevel(EMS_50);
  crystal(PDX_ON);
  power(PW_ON);
  softReset();
  chargePumps(CIA_80);
}

/* Debug Function *//*
void NS73M::debug()
{
 Serial.print("R0:");
 Serial.print(R0, BIN);
 Serial.print(":");
 Serial.println(R0, DEC);
 Serial.print("R1:");
 Serial.print(R1, BIN);
 Serial.print(":");
 Serial.println(R1, DEC);
 Serial.print("R2:");
 Serial.print(R2, BIN);
 Serial.print(":");
 Serial.println(R2, DEC);
 Serial.print("R3:");
 Serial.print(R3, BIN);
 Serial.print(":");
 Serial.println(R3, DEC);
 Serial.print("R4:");
 Serial.print(R4, BIN);
 Serial.print(":");
 Serial.println(R4, DEC);
 Serial.print("R6:");
 Serial.print(R6, BIN);
 Serial.print(":");
 Serial.println(R6, DEC);
 Serial.print("R8:");
 Serial.print(R8, BIN);
 Serial.print(":");
 Serial.println(R8, DEC);
}*/

void NS73M::spiSend(uint8_t reg, uint8_t data)
{
  uint8_t x;
  digitalWrite(LA, LOW);

  for(x = 0 ; x < 4 ; x++)
  {
    digitalWrite(CK, LOW);
    digitalWrite(DA, (reg >> x) & 1);  
    digitalWrite(CK, HIGH);	
  }

  for(x = 0 ; x < 8 ; x++)	  
  {
    digitalWrite(CK, LOW);	 
    digitalWrite(DA, (data >> x) & 1);  
    digitalWrite(CK, HIGH);
  }
  delayMicroseconds(1);		

  digitalWrite(LA, HIGH);
  delayMicroseconds(4);
  digitalWrite(LA, LOW);

  digitalWrite(CK, LOW);
}

EDIT:
Une version beaucoup plus récente de ma librairie est désormais disponible sur mon compte github à l’adresse suivante :
https://github.com/skywodd/NS73M_arduino_library
(il y a quelques modifications dans les noms de fonctions mais rien de bien terrible ;))

Enjoy 😉

Note: Je tient à rappeler que brouiller volontairement une fréquence FM même sur une courte porté/durée est illégal.
Donc même si ça peut paraitre trés cool comme systéme pensez à prendre vos responsabilité en l’utilisant 😉

Discussion

9 réflexions sur “[­Projet Arduino] TrololoFM (base NS73M)

  1. Bon projet qui rappelle le projet Trololol FM de Furrtek…
    A quand une vidéo live ?

    voici le lien de Furrtek:
    http://furrtek.free.fr/?p=videos&raise=182

    Publié par Guigui | 12 février 2012, 11 h 49 min
    • C’est justement après avoir vu la vidéo de furrtek que j’ai eu cette idée de projet.

      En faite c’est plus une excuse pour reprendre ma librairie NS73M qu’un vrai projet 😉

      Pas de vidéo prévu pour le moment, j’ai vraiment pas le temps …

      Publié par skywodd | 12 février 2012, 12 h 04 min
  2. Un seul mot : Waow !

    Merci pour ton blog, je le lis régulièrement et c’est franchement bien détaillé 🙂

    Publié par Nicolas fritz | 13 février 2012, 14 h 36 min
  3. Excellent, bel assemblage de composants puissants 🙂 Dommage qu’il y ait pas l’app live en vidéo mais je sais bien que ça demande pas mal de temps et de chance…

    Publié par furrtek | 17 juillet 2012, 9 h 39 min
    • Yea salut Furrtek 🙂

      Pour la vidéo c’était prévu, le probléme c’est que je n’ai trouvé aucun commerce utilisant la radio pour meubler l’ambiance (le big fail).
      Du coup je m’était rabattu sur les mec en voiture avec la sono à fond, mais le temps de chopper la caméra, d’allumer l’émetteur, de changer la fréquence ils sont déjà loin :/

      Pour la puissance en sortie c’est pas énorme, seulement 2mW.
      Du coup j’avais prévu d’utiliser une vrai antenne FM et une ampli FM intégré VMR6700 (max 100mW) pour booster un peu.
      Mais je manque cruellement de temps pour faire tout ce qui ce trouve sur ma TODO list …

      Publié par skywodd | 17 juillet 2012, 14 h 08 min
  4. Salut ! Quels est le module FM que tu utilises ? Puis-je avoir sa référence ? Merci ! 🙂

    Publié par Kouaaks | 27 décembre 2012, 15 h 47 min
  5. Ah désolé, enfaite c’est marqué dans le titre : NS73M.
    Sinon bon très projet! J’aime =D

    Publié par Kouaaks | 27 décembre 2012, 15 h 49 min
  6. Peut on avoir le schéma du montage ?

    Publié par Simon | 3 juillet 2013, 13 h 39 min

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Skyduino devient Carnet du Maker

Le site Carnet du Maker remplace désormais le blog Skyduino pour tout ce qui touche à l'Arduino, l'informatique et au DIY.