BACK
Home Page

Phone Spam - Project

The entire project is Documented and open (except for the server-side part, for security reasons).
Feel free to use this schematics.
Phase 1 - caller ID
Read caller ID from Tip and Ring with the HT9032D decoder chip.
Phase 2 - caller ID
Arduino code to get the caller ID.
Phase 3 - WiFi chip
A small and cheap WiFi Transmitter.
Phase 4 - Access Point
How to connect to an access point.
Phase 5 - Post Request
Sending phone number to a server.
Phase 6 - LCD display
A LCD display for the caller name.

Phase 2 - caller ID

What we expect

As descripted on the Phase 1, we get some pulses at 1200 bauds from the FSK chip.
Every provider can give other kind of informations or messages.
In Switzerland we use the ETSI FSK protocolWe can only get the single and multiple message type (month/day/hour/minute/phone number[/name]).
If you need more documentation, there is a good page selling caller-id simulators and others:
Check http://www.adventinstruments.com or download a PDF with all infos: CID1500_UG_R7.pdf.

Decode message

After the first ring, we will get a sequence of 1 and 0: 01010101, 30 times! At this point we get the total bytes to read.
Then, we get the date/time and caller number (or P if private).
* it is also possible that the provider send the caller name (multiple message type), but it is more used on business phones.

Swiss protocol: ETSI FSK

COMMANDBYTESExpected
Calling info300x55, 30 times
Message type10x80 calling message
Info length10x16
Message header20x01 and 0x08, type 1 and 8 bytes
Message body8month, day, hours, minutes as ASCII numbers (0x31 = '1')
Message header20x02 and 0x0A, type 2 and 10 bytes
Message body10Phone number

Arduino usage

Memory usage for FSK:
20% - Flash (max 32kb)

16% - SRAM (max 2048 bytes)

0% - EEPROM (max 1024 bytes)

On the flash, we have also the bootloader (10%), the SoftwareSerial library and the message strings for the terminal (so we don't need SRAM).

Arduino Code

Main page tab:
//*********************************************************************//
//                            PHONE SPAM PROJECT                       //
//                       ===========================                   //
// * on the phonebook but the spammers will call you without respect?  //
// This project is done to try to remove so much calls as possible.    //
//                                                                     //
// Open Readme or Changelog to read more.                              //
//                                                                     //
// Version:  1.00 - june 2015                                          //
// Author:   Adriano Petrucci                                          //
// Web Page: http://phonespam.petrucci.ch                              //
//**********************************************************************

#include <avr/pgmspace.h>
#include <SoftwareSerial.h>

#define VERSION            1.00          // Program version
#define REVISION           2             // Revision, until new version

// Define all Arduino PINS
#define PIN_RX_HT9032      4             // Receive data at 1200 bauds
#define PIN_TX_HT9032      3             // Not used. We need it for the library

int iTempNumberOk = -1;

void setup()
{
  ht9032_setup();                        // Setup the HT9032 decoder
  serial_setup();                        // Setup serial for terminal

  delay(100);                            // Leave time for other devices to init.
  serial_init();                         // Write something to the serial
}

void loop()
{
  // Check if we got a phone number from decoder.
  if (ht9032_loop())
  {
    serial_showByte();
    // If we got a phone number, show it to the terminal
    serial_showNumber();
  }
  else
  {
    // No phone number, check if we got a byte
    if(ht9032_GetLastReceivedByte() > 0 && ht9032_IsReadingNumber())
    {
      // If we got a byte, show it to the terminal
      serial_showByte();
    }
  }
}

Serial tab:

// save some chars in Flash
const char SERIAL_TITLE[] PROGMEM   = {"PHONESPAM MODULE"};
const char SERIAL_LINE[] PROGMEM    = {"================"};
const char SERIAL_VERSION[] PROGMEM = {"Version: "};
const char SERIAL_AUTHOR[] PROGMEM  = {"Adriano Petrucci"};
const char SERIAL_PHONE_RECEIVED[] PROGMEM = {"Phone number received: "};
const char SERIAL_CHAR_RECEIVED[] PROGMEM  = {",0x"};
const char SERIAL_POINT[] PROGMEM  = {"."};
const char SERIAL_SPACE[] PROGMEM  = {" "};
const char SERIAL_POINTS[] PROGMEM = {":"};
const char SERIAL_MONTH[] PROGMEM  = {"JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC___"};


void serial_setup()
{
  Serial.begin(9600);
  while (!Serial);
}

void serial_printLine(const char text[], char len, bool bNewLine)
{
  for (char k = 0; k < len; k++)
  {
    Serial.print((char)pgm_read_byte_near(text + k));
  }
  if(bNewLine)
  {
    Serial.println();
  }
}
void serial_printMonth(const char text[])
{
  for (char k = 0; k < 3; k++)
  {
    Serial.print((char)pgm_read_byte_near(text + k));
  }
}

void serial_init()
{
  serial_printLine(SERIAL_TITLE, strlen(SERIAL_TITLE), true);
  serial_printLine(SERIAL_LINE, strlen(SERIAL_LINE), true);
  serial_printLine(SERIAL_VERSION, strlen(SERIAL_VERSION), false);
  Serial.print(VERSION);
  serial_printLine(SERIAL_POINT, strlen(SERIAL_POINT), false);
  Serial.println(REVISION);
  serial_printLine(SERIAL_AUTHOR, strlen(SERIAL_AUTHOR), true);
  serial_printLine(SERIAL_LINE, strlen(SERIAL_LINE), true);
}

void serial_showNumber()
{
  byte msgLen = ht9032_GetMessageLength();
  char *msg = ht9032_GetMessage();
  byte month = 0;
  byte day = 0;
  byte hours = 0;
  byte minutes = 0;
  byte phoneNr[16];
  byte phoneNrLen;
  
  month = (msg[2] - '0') * 10;
  month += (msg[3] - '0');
  if(month >= 12 || month == 0) month = 11;
  else month--;
  day = (msg[4] - '0') * 10;
  day += (msg[5] - '0');
  hours = (msg[6] - '0') * 10;
  hours += (msg[7] - '0');
  minutes = (msg[8] - '0') * 10;
  minutes += (msg[9] - '0');

  phoneNrLen = min(16, msgLen - msg[1]);
  for(char i=0;i<phoneNrLen;i++)
  {
    phoneNr[i] = char(msg[2 + msg[1] + 2 + i]);
  }
  
  serial_printLine(SERIAL_PHONE_RECEIVED, strlen(SERIAL_PHONE_RECEIVED), true);
  Serial.print((int)day);
  serial_printLine(SERIAL_POINT, strlen(SERIAL_POINT), false);
  serial_printMonth(&SERIAL_MONTH[month*3+0]);
  serial_printLine(SERIAL_SPACE, strlen(SERIAL_SPACE), false);
  Serial.print((int)hours);
  serial_printLine(SERIAL_POINTS, strlen(SERIAL_POINTS), false);
  Serial.print((int)minutes);
  serial_printLine(SERIAL_SPACE, strlen(SERIAL_SPACE), false);
  serial_printLine(SERIAL_SPACE, strlen(SERIAL_SPACE), false);
  for(char i=0;i<phoneNrLen;i++)
  {
    Serial.print(char(phoneNr[i]));
  }
  Serial.println();
}

void serial_showByte()
{
  serial_printLine(SERIAL_CHAR_RECEIVED, strlen(SERIAL_CHAR_RECEIVED), false);
  Serial.print((byte)ht9032_GetLastReceivedByte(), HEX);
}


ht9032 tab:

#define MAX_HT9032_CHARS    25

byte byHt9032Step = 0x00;
char chHt9032Message[MAX_HT9032_CHARS];
byte byHt9032MessageLen = 0;
byte byHt9032MsgIndex = 0;
byte byRead = 0;

SoftwareSerial ht9032_Serial(PIN_RX_HT9032, PIN_TX_HT9032); // RX, TX

void ht9032_setup()
{
    // set the baud rate for the SoftwareSerial port
  ht9032_Serial.begin(1200);
}

bool ht9032_loop()
{
  byRead    = 0;
  
  if(ht9032_Serial.available() > 0)  
  {
    byRead = ht9032_Serial.read();  
    if(byRead == 0x00 || byRead > 0xA0) return false;
    switch(byHt9032Step)
    {
             // Wait until data is here
      case 0x00:
                  // Data begins with 0x55
                if(byRead == 0x55)  
                {
                  byHt9032Step     = 0x01;
                  byHt9032MsgIndex = 0x01;
                }
                break;
             // We got a byte/ring! Filter 0x55 bytes (we don't need the 10101010101 ring)
      case 0x01:
                if(byRead == 0x55) 
                {
                  byHt9032MsgIndex++;
                }                        
                else
                {
                  byHt9032Step     = 0x00;
                  byHt9032MsgIndex = 0x00;
                }
                  // After 5 times, we probably get the phone info
                if(byHt9032MsgIndex >= 0x05)
                {
                  byHt9032Step     = 0x02;
                }
                break;
             // Wait until end of 0x55
      case 0x02:
                if(byRead != 0x55)
                {
                  if(byHt9032MsgIndex >= 0x18)  // at least 24 times!
                  {
                    if(byRead >= 0x80)  // Calling message
                    {
                      byHt9032Step     = 0x03;
                      Serial.print("Codifica:");
                      Serial.println((int)byRead);
                    }
                    else
                    {
                      byHt9032Step     = 0x04;
                      byHt9032MsgIndex = 0x00;
                      byHt9032MessageLen = min(MAX_HT9032_CHARS-1, byRead);
                      Serial.print("Lunghezza:");
                      Serial.println((int)byRead);
                    }
                  }
                  else
                  {
                    byHt9032Step     = 0x00;
                    byHt9032MsgIndex = 0x00;
                  }
                }
                else
                {
                  byHt9032MsgIndex++;
                }
                break;
             // Get message length
      case 0x03:
                byHt9032Step     = 0x04;
                byHt9032MsgIndex = 0x00;
                byHt9032MessageLen = min(MAX_HT9032_CHARS-1, byRead);
                break;
             // Get messages
      case 0x04:
                chHt9032Message[byHt9032MsgIndex++] = byRead;  
                if( byHt9032MsgIndex >= byHt9032MessageLen ) 
                {
                  byHt9032Step     = 0x00;
                  byHt9032MsgIndex = 0x00;
                  return true;            
                }
                break;
       default:
                byHt9032Step = 0x00; 
                break;
    }
  }
  
  return false;
}

int ht9032_GetMessageLength()
{
  return byHt9032MessageLen;
}

char *ht9032_GetMessage()
{
  return chHt9032Message;
}

char ht9032_GetLastReceivedByte()
{
  return (char)byRead;
}

bool ht9032_IsReadingNumber()
{
  return (byHt9032Step > 2);
}


Comments:

© Phonespam - 2015Adriano Petrucci Progetto personale per cercare di rendere la vita difficile a questi bas*ardi.