Digital Intercom

 

History

This project was inspired by my girlfriend, who asked me to build an intercom for our house. There are many ways to build an intercom; an example is batteries in series with 2 telephones, a key switch and an amplifier. I felt this was far too simple. I decided to build an intercom with an MCU which digitalizes a voice and then sends it serially and then regenerates the analog signal. I equipped the microphone with an ACG to ensure that anyone in between 1 inch and 10 feet from the microphone will sound good. After that I send the analog signal to the A/D of my MCU which digitalizes the voice and sends it serially to the other intercom that you have previously set the "address" for. The digital signal is sent to an RS422 interface, which sends it to a RS422 hub, which then broadcasts the data to the other intercoms. The addressed intercom takes the data and regenerates the analog signal via a PWM and a simple analog filter. I found a really cool 3 Watt Amplifier which works at 12 volts with a pin to control the output volume.

 

 

Features

puce LCD
puce AGC
puce Simple power amplifier with volume control
puce PWM generated D/A
puce Sine wave generator for key sound and pre-tone

 

Pictures

Click to enlarge

PCB

PCB Mount

 

Front

Finish

 

 

Sources codes & Schematics

-Schematic of the intercomm in PDF format

-Schematic of the hub in PDF format

//*****************************************************************************
// InterCom
// Version 1.0 Sep 2005
//
// 1.0 -> -Everything is new
//
// Sylvain Bissonnette
//*****************************************************************************
// Editor : UltraEdit32
//*****************************************************************************
//
//                    R E T U R N   S T A C K   3 2
//                          X T A L  16 MHZ
//                      BootLoader of 1024 word
//
//*****************************************************************************
//
//                          F U S E   B I T
//
//( )7      ( )6     ( )BL12 ( )BL11  ( )BL02   ( )BL01    ( )Lock2   ( )Lock1
//( )7      ( )6     ( )     ( )      ( )       ( )M103C   ( )WDTON   ( )
//( )OCDEN  ( )JTAGE (X)SPIEN(X)CKOPT (X)EESAVE ( )BOOTSZ1 (X)BOOTSZ0 (X)BOOTRST
//(X)BODLEV (X)BODEN ( )SUT1 (X)SUT0  ( )CKSEL3 (X)CKSEL2  ( )CKSEL1  ( )CKSEL0
//
//*****************************************************************************
//                          P I N   U S A G E
//
// PA0 -> GND
// PA1 -> A/D input from Microphone
// PA2 -> GND
// PA3 -> GND
// PA4 -> GND
// PA5 -> GND
// PA6 -> GND
// PA7 -> GND
//
// PB0 -> Keypad ROW1
// PB1 -> Keypad ROW2
// PB2 -> Keypad ROW3
// PB3 -> Keypad ROW3
// PB4 -> Keypad COL1
// PB5 -> Keypad COL2
// PB6 -> Keypad COL3
// PB7 -> Keypad COL4
//
// PC0 -> LCD DB7
// PC1 -> LCD DB6
// PC2 -> LCD DB5
// PC3 -> LCD DB4
// PC4 -> LCD E
// PC5 -> LCD R/W
// PC6 -> LCD RS
// PC7 -> LCD BackLight
//
// PD0 -> Net_RX
// PD1 -> Net_TX
// PD2 -> +5
// PD3 -> LED
// PD4 -> PWM Volume
// PD5 -> PWM Voice
// PD6 -> Ampli Standby
// PD7 -> LCD Contrast
//
//*****************************************************************************
//                        T I M E R   U S A G E
//
// Timer 0 is use for 20khz sampling & reproducing voice
// Timer 1 is use for 62.5khz PWM voice reproducing and volume
// Timer 2 is use for LCD Contrast
// Timer 3 not use
//
//*****************************************************************************

//*****************************************************************************
//                            I N C L U D E
//*****************************************************************************
#include <iom32v.h>
#include <shortnametype.h>
#include <macros.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <eeprom.h>

//*****************************************************************************
//                            D E F I N E
//*****************************************************************************
#define VERSION                 10
#define TRUE                    1
#define FALSE                   0
#define XTAL                    16000000

#define VOICEBUFFER             64

#define OFF                     0
#define TALK                    1
#define LISTEN                  2
#define TONE                    3
#define BUSY                    4

#define PWM_VOICE               0x20
#define PWM_VOLUME              0x10
#define AMPLI_STANDBY           0x40

#define EEPROM_VOLUME           1
#define EEPROM_ADDRESS          2
#define EEPROM_KEYSOUND         3
#define EEPROM_KEYSOUNDVOLUME   4
#define EEPROM_KEYSOUNDTONE     5
#define EEPROM_KEYSOUNDLEN      6
#define EEPROM_BROADCAST        7

#define LED                     0x08

#define MAXITEM                 20

// Network
#define NET_DDR                 DDRD
#define NET_PIN                 PIND
#define NET_PORT                PORTD
#define NET_RX                  0x01
#define NET_TX                  0x02

#define NET_UBRRH               UBRRH
#define NET_UBRRL               UBRRL
#define NET_UCSRA               UCSRA
#define NET_UCSRB               UCSRB
#define NET_UCSRC               UCSRC
#define NET_UDR                 UDR

#define NET_SPEED               500000
#define NET_GET_ADDRESS         EEPROMread(EEPROM_ADDRESS);

// LCD
#define LCD_D7                  0x01
#define LCD_D6                  0x02
#define LCD_D5                  0x04
#define LCD_D4                  0x08
#define LCD_E                   0x10
#define LCD_RW                  0x20
#define LCD_RS                  0x40
#define LCD_BACKLIGHT           0x80

#define LCD_PIN                 PINC
#define LCD_DDR                 DDRC
#define LCD_PORT                PORTC

#define LCD_DATA                0x01
#define LCD_CTRL                0x00

#define LCD_C_BLINK_ON          0x09
#define LCD_C_BLINK_OFF         0xfe
#define LCD_C_ON                0x0a
#define LCD_C_OFF               0xfd
#define LCD_DISPLAY_ON          0x0c
#define LCD_DISPLAY_OFF         0xfb
#define LCD_BRIGHT_25           0x23
#define LCD_BRIGHT_50           0x22
#define LCD_BRIGHT_75           0x21
#define LCD_BRIGHT_100          0x20
#define LCD_BACKLIGHT_ON        0x24
#define LCD_BACKLIGHT_OFF       0x25

// Key
#define KEY_PIN                 PINB
#define KEY_DDR                 DDRB
#define KEY_PORT                PORTB

// Keypad
#define ROW1                    0x02
#define ROW2                      0x04
#define ROW3                      0x08
#define ROW4                      0x10
#define COL1                      0x20
#define COL2                      0x40
#define COL3                      0x80
#define COL4                      0x80

#define RESET                   20

//*****************************************************************************
//           C O N S T A N T                                  
//*****************************************************************************
// SineTable
const ushort SineTable[256] =  {133,136,139,142,
                                         145,149,152,155,
                                         158,161,164,167,
                                         169,172,175,178,
                                         181,184,186,189,
                                      192,194,197,200,
                                      202,205,207,209,
                                      212,214,216,218,
                                      220,222,224,226,
                                      228,230,232,233,
                                      235,237,238,240,
                                      241,242,243,245,
                                      246,247,248,248,
                                      249,250,251,251,
                                      252,252,252,253,
                                      253,253,253,253,
                                      253,253,252,252,
                                      252,251,251,250,
                                      249,248,248,247,
                                      246,245,243,242,
                                      241,240,238,237,
                                      235,233,232,230,
                                      228,226,224,222,
                                      220,218,216,214,
                                      212,209,207,205,
                                      202,200,197,194,
                                      192,189,186,184,
                                      181,178,175,172,
                                      169,167,164,161,
                                      158,155,152,149,
                                      145,142,139,136,
                                      133,130,127,124,
                                      121,118,115,112,
                                      109,105,102,99,
                                      96,93,90,87,
                                      85,82,79,76,
                                      73,70,68,65,
                                      62,60,57,54,
                                      52,49,47,45,
                                      42,40,38,36,
                                      34,32,30,28,
                                      26,24,22,21,
                                      19,17,16,14,
                                      13,12,11,9,
                                      8,7,6,6,
                                      5,4,3,3,
                                      2,2,2,1,
                                      1,1,1,1,
                                      1,1,2,2,
                                      2,3,3,4,
                                      5,6,6,7,
                                      8,9,11,12,
                                      13,14,16,17,
                                      19,21,22,24,
                                      26,28,30,32,
                                      34,36,38,40,
                                      42,45,47,49,
                                      52,54,57,60,
                                      62,65,68,70,
                                      73,76,79,82,
                                      85,87,90,93,
                                      96,99,102,105,
                                      109,112,115,118,
                                      121,124,127,127};

//*****************************************************************************
//                            P R O T O T Y P E
//*****************************************************************************
void main(void);
void DoVolume(void);
void DoKey(ushort ReGen);
void SetKeySoundLen(void);
void SetKeySoundTone(void);
void SetKeySoundVolume(void);
void SetKeySound(void);
void SetBroadCastEnable(void);
void SetStationAddress(void);
void StationCall(ushort Station);
void BroadCastCall(void);
void _StackOverflowed(char c);
void Led(void);
void Info(void);
void Delay(ushort Del);

// A/D
void ADInit(void);
void ADStart(void);
void ADDone(void);

// Voice
void VoiceEnginInit(void);
void VoiceEngin(void);
void VoiceVolume(ushort Vol);

// Network
void NetInit(void);
void NetSendCommand(ushort To,ushort Command);
void NetDirectWriteByte(ushort Byte);
void NetWriteByte(ushort Byte);
ushort NetReadByte(void);
ushort NetGetInByteCount(void);
void NetRxByte(void);
void NetTxByte(void);
void NetGetAddress(void);

// LCD
void LCDInit(ushort x,ushort y);
void LCDOff(void);
void LCDClrSCR(void);
void LCDGotoXY(ushort,ushort);
ushort LCDWhereX(void);
ushort LCDWhereY(void);
void LCDWriteString(char *);
void LCDWriteConstString(const char *);
void LCDWriteChar(char);
void LCDWriteData(ushort,ushort);
ushort LCDReadData(ushort rs);
void LCDCreateCHR(ushort chnumber, char *ptr);
void LCDWait(void);
void LCDDelay50us(int Delay);
void LCDTextAttr(ushort attribute);
void LCDContrast(ushort Cont);

// Key
void KeyInit(void);
ushort KeyLook(void);
void KeyScan(void);

//*****************************************************************************
//                      G L O B A L   V A R I A B L E
//*****************************************************************************

// LCD
ushort MaxX, MaxY, LCDStat;
char Text[20];

// Keypad
ushort Key;
ushort KeySound;
ushort KeySoundVolume;
ushort KeySoundTone;
ushort KeySoundLen;

// Network
ushort  NetAddress;
ushort DataInBuffer[VOICEBUFFER];
ushort *DataInBufferWrite;
ushort *DataInBufferRead;
uint DataInBufferQte;

ushort DataOutBuffer[VOICEBUFFER];
ushort *DataOutBufferWrite;
ushort *DataOutBufferRead;
uint DataOutBufferQte;

ushort InterCommMode;
ushort IncommingCall;
ushort Volume = 0x80;
ushort Tone = 8;

// Display
char DisplayName[MAXITEM][13];
char DisplayValue[MAXITEM][6];
int DisplayQTE;

// Others
ushort BroadCastEnable;

//*****************************************************************************
//                      M A I N
//*****************************************************************************
void main()
{
  WDR();
  WDTCR = 0x0f; // Watch Dog enable
  LCDInit(20,2);
  KeyInit();
  NetInit();
  ADInit();
  VoiceEnginInit();

  SEI(); //re-enable interrupts

  EEPROM_READ(EEPROM_VOLUME, Volume);
  EEPROM_READ(EEPROM_KEYSOUND, KeySound);
  EEPROM_READ(EEPROM_KEYSOUNDVOLUME, KeySoundVolume);
  EEPROM_READ(EEPROM_KEYSOUNDTONE, KeySoundTone);
  EEPROM_READ(EEPROM_KEYSOUNDLEN, KeySoundLen);
  EEPROM_READ(EEPROM_BROADCAST, BroadCastEnable);

  if (KeySoundTone > 59) KeySoundTone = 59;
  if (KeySoundLen > 10) KeySoundLen = 10;

  Info();
  InterCommMode = TONE;
  VoiceVolume(0x40);
  Delay(50);
  LCDClrSCR();
  VoiceVolume(0);
  InterCommMode = OFF;
  IncommingCall = FALSE;
  DoKey(TRUE);

  while(1)
  {
    WDR();
    _StackCheck();

    if (KeyLook() == RESET) while(TRUE);
    if ((!IncommingCall) && (InterCommMode != BUSY)) DoKey(FALSE);
    if (IncommingCall) DoVolume();
  }
}

/******************************************************************************

Name:       void DoKey(void)

Description:  

Input:         none

Output:        none

Misc:      

******************************************************************************/
void DoVolume(void)
{
  static int Ticker,VolumeChange=FALSE;

  Ticker++;
  Key = KeyLook();

  if ((Key == 11) && (Volume < 255)) Volume++;
  if ((Key == 10) &&(Volume > 1)) Volume--;

  if (Key != 0xff)
  {
    Ticker = 0;
    VoiceVolume(Volume);
    VolumeChange = TRUE;
    LCDGotoXY(1,2);
    LCDWriteConstString("                    \0");
    LCDGotoXY(1,2);
    csprintf(&Text[0],"    Volume :%d  \0",Volume);
    LCDWriteString(&Text[0]);
    Delay(1);
    Key = 0xff;
  }

  if ((VolumeChange == TRUE) && (Ticker > 1000))
  {
    EEPROM_WRITE(EEPROM_VOLUME, Volume);
    VolumeChange = FALSE;
  }
}

/******************************************************************************

Name:       void DoKey(void)

Description:  

Input:         none

Output:        none

Misc:      

******************************************************************************/
void DoKey(ushort ReGen)
{
  static ushort KeyFirst,KeySecond,Value,Update;

  Update = FALSE;

  if (ReGen)
  {
    LCDClrSCR();
    LCDGotoXY(1,1);
    LCDWriteConstString("  InterComm  V:1.0\0");
    LCDGotoXY(1,2);
    LCDWriteData(LCD_DATA,KeySecond+48);
    LCDWriteData(LCD_DATA,KeyFirst+48);
    Value = (KeySecond * 10) + KeyFirst;
    Update = TRUE;
  }
  else
  {
    KeyScan();

    if ((Key != 0xff) && (Key != 10) && (Key != 11))
    {
      KeySecond = KeyFirst;
      KeyFirst = Key;
      LCDGotoXY(1,2);
      LCDWriteData(LCD_DATA,KeySecond+48);
      LCDWriteData(LCD_DATA,KeyFirst+48);
      Value = (KeySecond * 10) + KeyFirst;
      Update = TRUE;
      Key = 0xff;
    }
  }

//--------------------

  if (Update == TRUE)
  {
    LCDGotoXY(3,2);
    if (Value == 0) LCDWriteConstString("->Broadcast Call #\0");
    else if ((Value >= 1) && (Value < 40)) LCDWriteConstString("->Calling #       \0");
    else if (Value == 99) LCDWriteConstString("->Set Address #   \0");
    else if (Value == 98) LCDWriteConstString("->Set Key Sound # \0");
    else if (Value == 97) LCDWriteConstString("->Set Key Tone # \0 ");
    else if (Value == 96) LCDWriteConstString("->Set Key Volume #\0");
    else if (Value == 95) LCDWriteConstString("->Set Tone Len # \0");
    else if (Value == 94) LCDWriteConstString("->Set BroadCast # \0");
    else if ((Value >= 40) && (Value < 95)) LCDWriteConstString("->                \0");
  }

//--------------------

  if (Key == 11)
  {
    Key = 0xff;
    if (Value == 0) BroadCastCall();
    else if ((Value >= 0) && (Value < 40)) StationCall(Value);
    else if (Value == 99) SetStationAddress();
    else if (Value == 98) SetKeySound();
    else if (Value == 97) SetKeySoundTone();
    else if (Value == 96) SetKeySoundVolume();
    else if (Value == 95) SetKeySoundLen();
    else if (Value == 94) SetBroadCastEnable();
  }
}

/******************************************************************************

Name:           SetKeySoundLen(void)

Description:  

Input:           none

Output:          none

Misc:      

******************************************************************************/
void SetKeySoundLen(void)
{
  static ushort KeyFirst,KeySecond,Value;

  LCDClrSCR();
  LCDGotoXY(1,1);
  csprintf(&Text[0],"Current Tone : %d\0",KeySoundLen);
  LCDWriteString(&Text[0]);
  LCDGotoXY(1,2);
  LCDWriteConstString("New Tone(00-10):00\0");

  while(TRUE)
  {
    WDR();
    KeyScan();
    if ((Key != 0xff) && (Key != 10) && (Key != 11))
    {
      KeySecond = KeyFirst;
      KeyFirst = Key;
      LCDGotoXY(17,2);
      LCDWriteData(LCD_DATA,KeySecond+48);
      LCDWriteData(LCD_DATA,KeyFirst+48);
      Value = (KeySecond * 10) + KeyFirst;
      if (Value < 11) KeySoundLen = Value;
      Key = 0xff;
    }

    if (Key == 11)
    {
      Key = 0xff;
      if ((Value >= 0) && (Value < 11))
      {
        EEPROM_WRITE(EEPROM_KEYSOUNDLEN, Value);
        LCDGotoXY(1,1);
        LCDWriteConstString("  New Value Saved   \0");
        Delay(75);
        LCDGotoXY(1,1);
        LCDWriteConstString("  ---------------   \0");
        DoKey(TRUE);
        return;
      }
      else
      {
        LCDGotoXY(1,1);
        LCDWriteConstString(" Value Out Of Range \0");
        Delay(75);
        LCDGotoXY(1,1);
        LCDWriteConstString(" ------------------ \0");
        DoKey(TRUE);
        return;
      }
    }
  }
}

/******************************************************************************

Name:           SetKeySoundTone(void)

Description:  

Input:           none

Output:          none

Misc:      

******************************************************************************/
void SetKeySoundTone(void)
{
  static ushort KeyFirst,KeySecond,Value;

  LCDClrSCR();
  LCDGotoXY(1,1);
  csprintf(&Text[0],"Current Tone : %d\0",KeySoundTone);
  LCDWriteString(&Text[0]);
  LCDGotoXY(1,2);
  LCDWriteConstString("New Tone(00-59):00\0");

  while(TRUE)
  {
    WDR();
    KeyScan();
    if ((Key != 0xff) && (Key != 10) && (Key != 11))
    {
      KeySecond = KeyFirst;
      KeyFirst = Key;
      LCDGotoXY(17,2);
      LCDWriteData(LCD_DATA,KeySecond+48);
      LCDWriteData(LCD_DATA,KeyFirst+48);
      Value = (KeySecond * 10) + KeyFirst;
      if (Value < 59) KeySoundTone = Value;
      Key = 0xff;
    }

    if (Key == 11)
    {
      Key = 0xff;
      if ((Value >= 0) && (Value <59))
      {
        EEPROM_WRITE(EEPROM_KEYSOUNDTONE, Value);
        LCDGotoXY(1,1);
        LCDWriteConstString("  New Value Saved   \0");
        Delay(75);
        LCDGotoXY(1,1);
        LCDWriteConstString("  ---------------   \0");
        DoKey(TRUE);
        return;
      }
      else
      {
        LCDGotoXY(1,1);
        LCDWriteConstString(" Value Out Of Range \0");
        Delay(75);
        LCDGotoXY(1,1);
        LCDWriteConstString(" ------------------ \0");
        DoKey(TRUE);
        return;
      }
    }
  }
}

/******************************************************************************

Name:           SetKeySoundVolume(void)

Description:  

Input:           none

Output:          none

Misc:      

******************************************************************************/
void SetKeySoundVolume(void)
{
  static ushort KeyFirst,KeySecond,Value;

  LCDClrSCR();
  LCDGotoXY(1,1);
  csprintf(&Text[0],"Current Key Vol:%d\0",KeySoundVolume);
  LCDWriteString(&Text[0]);
  LCDGotoXY(1,2);
  LCDWriteConstString("New Key Vol 00-99:00\0");

  while(TRUE)
  {
    WDR();
    KeyScan();
    if ((Key != 0xff) && (Key != 10) && (Key != 11))
    {
      KeySecond = KeyFirst;
      KeyFirst = Key;
      LCDGotoXY(19,2);
      LCDWriteData(LCD_DATA,KeySecond+48);
      LCDWriteData(LCD_DATA,KeyFirst+48);
      Value = (KeySecond * 10) + KeyFirst;
      KeySoundVolume = Value;
      Key = 0xff;
    }

    if (Key == 11)
    {
      Key = 0xff;
      EEPROM_WRITE(EEPROM_KEYSOUNDVOLUME, Value);
      LCDGotoXY(1,1);
      LCDWriteConstString("  New Value Saved   \0");
      Delay(75);
      LCDGotoXY(1,1);
      LCDWriteConstString("  ---------------   \0");
      DoKey(TRUE);
      return;
    }
  }
}

/******************************************************************************

Name:           SetKeySound(void)

Description:  

Input:           none

Output:          none

Misc:      

******************************************************************************/
void SetKeySound(void)
{
  LCDClrSCR();
  LCDGotoXY(1,1);
  if (KeySound) LCDWriteConstString("Key Sound is ON     \0");
  else LCDWriteConstString("Key Sound is OFF    \0");
  LCDGotoXY(1,2);
  LCDWriteConstString("* To Toggle  #->Save\0");

  while(TRUE)
  {
    WDR();
    KeyScan();
    if ((Key != 0xff) && (Key == 10))
    {
      if (KeySound) KeySound = 0;
      else KeySound = 1;
      Key = 0xff;
      LCDGotoXY(1,1);
      if (KeySound) LCDWriteConstString("Key Sound is ON     \0");
      else LCDWriteConstString("Key Sound is OFF    \0");
    }

    if (Key == 11)
    {
      Key = 0xff;
      EEPROM_WRITE(EEPROM_KEYSOUND, KeySound);
      LCDGotoXY(1,1);
      LCDWriteConstString("  New Value Saved   \0");
      Delay(75);
      LCDGotoXY(1,1);
      LCDWriteConstString("  ---------------   \0");
      DoKey(TRUE);
      return;
    }
  }
}

/******************************************************************************

Name:           SetBroadCastEnable(void)

Description:  

Input:           none

Output:          none

Misc:      

******************************************************************************/
void SetBroadCastEnable(void)
{
  LCDClrSCR();
  LCDGotoXY(1,1);
  if (BroadCastEnable) LCDWriteConstString("BroadCast is ON     \0");
  else LCDWriteConstString("BroadCast is OFF    \0");
  LCDGotoXY(1,2);
  LCDWriteConstString("* To Toggle  #->Save\0");

  while(TRUE)
  {
    WDR();
    KeyScan();
    if ((Key != 0xff) && (Key == 10))
    {
      if (BroadCastEnable) BroadCastEnable = 0;
      else BroadCastEnable = 1;
      Key = 0xff;
      LCDGotoXY(1,1);
      if (BroadCastEnable) LCDWriteConstString("BroadCast is ON     \0");
      else LCDWriteConstString("BroadCast is OFF    \0");
    }

    if (Key == 11)
    {
      Key = 0xff;
      EEPROM_WRITE(EEPROM_BROADCAST, BroadCastEnable);
      LCDGotoXY(1,1);
      LCDWriteConstString("  New Value Saved   \0");
      Delay(75);
      LCDGotoXY(1,1);
      LCDWriteConstString("  ---------------   \0");
      DoKey(TRUE);
      return;
    }
  }
}

/******************************************************************************

Name:    &nb