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
|
|
LCD |
|
|
AGC |
|
|
Simple power amplifier with volume control |
|
|
PWM generated D/A |
|
|
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