Saturday, 28 March 2020
Main Menu
Home Home
Shop Shop
News News
Products Products
Application Notes Application Notes
Publications Publications
Links Links
Support Center Support Center
Downloads Downloads
Forum Forum
Resellers Resellers
Contact Us Contact Us
Updates Updates
MCS Wiki MCS Wiki
Online Help
BASCOM-8051 Help BASCOM-8051 Help
Contents in Cart
Show Cart
Your Cart is currently empty.
Search the Shop

Products Search

User Login


If you have problem after log in with disappeared login data, please press F5 in your browser

RSS News

AN #165 - RC2 sound / Voice playback (Part 1) Print
AN written by Evert Dekker
(This AN has also Part2, follow this link )

What is it?

Itís a very simple, only 2 resistors and 1 condensator, sound playback. And it sounds amazing good, check the TheFinalResult.mp3 file.

This is based on an article by Mariano Barron in the Circuit Cellar #180 July 2005. Due the copyright I canít publish the article here. You can buy your copy at the Circuit Cellar website.

The software we need to encode the WAV files is free available from the Circuit cellar ftp server, in this file there is also a short description how it works.

With the Rc Sound Encoder software we compress the WAV to RC2 coding. This coding will be stored in eeprom and played back with this simple ďSoundcardĒ

Every sample requires only 1 bit, so for 1 second 44,1kHz sound we need 5512 Bytes storage space. Itís not much but for most MCU too much to store in the flash or internal eeprom. Therefore we store the sound samples in an external i2c eeprom.



Schematic is very simple. Iím using a Mega128 running on 16MHz. I2c eeprom (24c256) is connected with the hardware i2c (scl/sda). Software i2c will not work, this is to slow, maybe it will work with 22050hz samples but I didnít try that.

In the upper right corner we have the Rc2 decoder and optional an low pass filter and a simple amplifier.



Even the timer isr calculation is simple Crystal/prescaler/sample rate = 16000000/1/44100 = 362 = &H016A .

If you like to use an other sample rate or crystal you need to recalculate the timer.



The document RC2-Howto.pdf describes how to make your own Eeprom file with your sound or speech, this document can be found in the Zip file. The zip contains also the used WAV files, the ready to run demo Eeprom hex file and some ASM files.



In all the routines are 16bits addressing used, therefore itís not possible to use Eepromís larger then 512KB. If you change the routines you can use more then one 512KB i2c eeprom (you can hook up 4 to 1 i2c bus), but the RC-coder software uses also 16bits addresses and thatís something that we cannot change.


Required tools

- Sound edit software, Windows sound recorder will do, but thereís always better

- RC Sound encoder

- Atmel Avr studio 4

- Bascom AVR

- I2C Eeprom programmer including software


The code

Code is written and tested in Bascom license.

Note from MCS

To make the conversion of the ASM files simpler, i added some VB code to Everts VB programmer that allow to generate the BIN out of the ASM files.  You do not need Studio in that case.  Also, some files were added for the Mega88 running at 8 Mhz.


' R2C Decoder voice playback
' Playback sound and voice with very simple hardware 2xR 1xC
' By Evert Dekker 2008 R2CDecoder@Evertdekker dotje com
' Created with Bascom-Avr:

$regfile = "m128def.DAT"
$crystal = 16000000
$baud = 19200
$hwstack = 50
$swstack = 50
$framesize = 40

$lib "I2C_TWI.LBX"  'Setting up i2c hardware bus
Config Twi = 400000 'Hardware i2c bus speed
Config Scl = Portd.0 'TWI (i2c) ports on the Mega128
Config Sda = Portd.1
Const Addressw = &B10100000 'slave write address eeprom
Const Addressr = &B10100001 'slave read address eeprom

Alias Porta.1 'Voice pin 1
Alias Porta.2 'Voice pin 2
Config Porta.1 = Output
Config Porta.2 = Output

Config Timer1 = Timer , Prescale = 1 , Compare A = Set , Clear Timer = 1 'Setting up the timer
Compare1a = &H016A  'Timer1 comparator
Enable Interrupts
Enable Compare1a
On Compare1a Timer1_int
Stop Timer1 'Stop the timer, not yet needed

'==== Declaration
Declare Sub Read_eeprom_word(byval Adress As Word , Valueword As Word)
Declare Sub Playsample(byval Sample As Byte)
Declare Sub Read_eeprom_index

Dim Samples As Word , Start_byte(10) As Word , Lenght(10) As Word 'If you have more then 10 voices programmed, then incr this here.
Dim Bytetodo As Word , Outbyte As Byte
Dim Temp As Byte , Tempw As Word , Lus As Byte
Dim Bitcount As Byte , Tempadress2 As Byte

'=== Main ===
'Read the eeprom index because we need to know number of samples, startadress and lenght
Print Samples ; " Samples present in the eeprom"
For Lus = 1 To Samples
Print Lus ; "e sample start at eeprom adress: &H" ; Hex(start_byte(lus)) ; " is &H" ; Hex(lenght(lus)) ; " bytes long."
Next For
Wait 3

For Lus = 1 To Samples
 Playsample Lus
Wait 1
Next Lus


'=== Sub routines ===
Sub Playsample(byval Sample As Byte)
= Lenght(sample) 'Number of bytes to be processed
= Start_byte(sample) * 2  'Index is in word, need now bytes so *2
I2cstart 'Generate start
I2cwbyte Addressw
= High(tempw) 'High(adress)
I2cwbyte Tempadress2  'highbyte adress of EEPROM
= Low(tempw)
I2cwbyte Tempadress2 'lowbyte adress of EEPROM
I2cstart 'repeated start
I2cwbyte Addressr
Start Timer1 'Start the timer and therefore the playback
If Bitcount = 7 Then '1 byte processed
I2crbyte Outbyte , Ack 'Read byte from eeprom
Decr Bytetodo '1 byte less todo
= 0 'Reset bits processed
End If
Loop Until Bytetodo = 0 'Do until all the bytes from the sample are processed
Stop Timer1 'Ready stop the timer
I2crbyte Temp , Nack 'read extra byte with Nack to finish the i2c bus
I2cstop  'Stop i2c
= 0 : Vp1 = 0 'Silence the voice pins
End Sub

= Vp1 'Voice pin2 is the previous setting of voice pin1
If Bitcount > 0 Then Shift Outbyte , Right , 1 'shift the bits out
= Outbyte.0 'Set voice pin1
Incr Bitcount 'Next bit

Sub Read_eeprom_index 'Find the start adresse of each Voice. Adress is stored as word
 Read_eeprom_word 0
, Samples '1e Byte in the eeprom contens the number of programmed samples and is the low byte of the first sample
= Low(samples) : Temp = Temp -1 '
For Lus = 0 To Temp 'Loop the number of Samples found
= Lus * 2 'Reading words, so steps 2
 Read_eeprom_word Tempw
, Start_byte(lus + 1) 'Read the start adres of the samples
= Start_byte(lus + 1)
= Tempw * 2 'Reading words, so steps 2
 Read_eeprom_word Tempw
, Lenght(lus + 1) 'Read the lenght of the sample from the eeprom
Rotate Lenght(lus + 1) , Left , 8 'Msb and Lsb are inverted so swap them
Next Lus
End Sub

Sub Read_eeprom_word(byval Adress As Word , Valueword As Word)
Local Tempadress As Byte , Valueh As Byte , Valuel As Byte,
I2cstart 'generate start
I2cwbyte Addressw 'slave adsress
= High(adress)
I2cwbyte Tempadress 'highbyte adress of EEPROM
= Low(adress)
I2cwbyte Tempadress 'lowbyte adress of EEPROM
I2cstart 'repeated start
I2cwbyte Addressr 'slave address (read)
I2crbyte Valuel , Ack 'read byte
I2crbyte Valueh , Nack
I2cstop 'generate stop
= Makeint(valuel , Valueh)
End Sub