RC2 Decoder sound / voice playback

What is it?

It’s an 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 2726 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.

Hardware

Schematic

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.

Timing
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.

Diy
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.

Limitation
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

 

The code
Code is written and tested in Bascom 1.11.9.0.001 license.

'------------------------------------------------------------------
'                      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: 1.11.9.0.100
'------------------------------------------------------------------

$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


Vp1 Alias Porta.1                                           'Voice pin 1
Vp2 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 ===
Do
Read_eeprom_index                                           '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

Loop
End



'=== Sub routines ===
Sub Playsample(byval Sample As Byte)
Bytetodo = Lenght(sample)                                   'Number of bytes to be processed
Tempw = Start_byte(sample) * 2                              'Index is in word, need now bytes so *2
I2cstart                                                    'Generate start
I2cwbyte Addressw
Tempadress2 = High(tempw)                                   'High(adress)
I2cwbyte Tempadress2                                        'highbyte adress of EEPROM
Tempadress2 = Low(tempw)
I2cwbyte Tempadress2                                        'lowbyte adress of EEPROM
I2cstart                                                    'repeated start
I2cwbyte Addressr
Start Timer1                                                'Start the timer and therefore the playback
Do
If Bitcount = 7 Then                                        '1 byte processed
   I2crbyte Outbyte , Ack                                   'Read byte from eeprom
    Decr Bytetodo                                           '1 byte less todo
    Bitcount = 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
Vp2 = 0 : Vp1 = 0                                           'Silence the voice pins
End Sub



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



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
      Temp = Low(samples) : Temp = Temp -1                  '
      For Lus = 0 To Temp                                   'Loop the number of Samples found
          Tempw = Lus * 2                                   'Reading words, so steps 2
          Read_eeprom_word Tempw , Start_byte(lus + 1)      'Read the start adres of the samples
          Tempw = Start_byte(lus + 1)
          Tempw = 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
   Tempadress = High(adress)
   I2cwbyte Tempadress                                      'highbyte adress of EEPROM
   Tempadress = 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
   Valueword = Makeint(valuel , Valueh)
End Sub

 

T-65 Upgrade

 

Back in the old days we had PTT, the dutch phone company. The only allowed phone to use was the one provided by the PTT. In the 80′ they allowed other brand of phones connected to there line, so the good old T-65 disappears to the garage.
Now the “retro” look is back in the interior design, so the T-65 is also trendy, but i wouldn’t work today anymore because it’s using puls dialing and modern pabx can only use tone dialing (DTMF). Cable, adsl modems and skype won’t work either with puls dialing.
On the net i found this simple schematic made by Frits k, it will upgrade the T-65 with DTMF and redial function. Check it out(sorry only dutch). Nice project to build.

 

T65
Pcb back
Finished pcb
Pcb buildin
PlayPause
previous arrow
next arrow
 
T65
Pcb back
Finished pcb
Pcb buildin
previous arrow
next arrow
Manchester coding

For wireless communication you need Manchester coding. Manchester code provides simple encoding with no long period without a level transition. This helps clock recovery.
Here ‘s is a simple sample for a transmitter and receiver written in Bascom-avr.
1 will be coded as 01
0 will be coded as 10
00 and 11 are invalid
For the receiving part in VB6 check here .

Declare Function Make_manchester(byval Temp As Byte) As Word
Declare Function Decode_manchester(byval Tempw As Word ) As Byte



'== Demo prog ==
Dim Lus As Byte
Do
For Lus = 0 To 255
   Tempword = Make_manchester(lus)
   Print Decode_manchester(tempword)
Next Lus
Loop
End

 

'Subroutines
Sub Make_manchester(byval Temp As Byte) As Word
Local Bit_number As Byte
Local Manchester As Word
Bit_number = 8
Do
Shift Manchester , Left , 2
Decr Bit_number
If Temp.bit_number = 1 Then
Manchester = Manchester + 1                                 '01
Else
Manchester = Manchester + 2                                 '10
End If
Loop Until Bit_number = 0
Make_manchester = Manchester
End Sub


Sub Decode_manchester(byval Tempw As Word ) As Byte
Local Bit_number As Byte
Local Manchester As Word
Bit_number = 8
Do
Shift Manchester , Left , 1
Decr Bit_number
Temp_1 = Tempw And &B1100_0000_0000_0000
If Temp_1 = &B0100_0000_0000_0000 Then Incr Manchester      '01
If Temp_1 = &B1100_0000_0000_0000 Or Temp_1 = 0 Then Set Data_error       '11 or 00
Shift Tempw , Left , 2
Loop Until Bit_number = 0
If Data_error = 0 Then
   Decode_manchester = Manchester
Else
   Decode_manchester = 0
End If
Reset Data_error
End Sub
Vectron Veft-factuur

For the Vecton POS system I have build different modules. This is the “Veft-factuur” module.
It’s a standalone invoice module for the Vectron-pos, it don’t need Vcom to operate. It’s using Veft as communication platform with the ecr’s.
Due the communication with Tcp/ip it’s possible to create global network with 1 invoice server. Therefore it’s possible that the customers visit different locations with 1 account.
Veft-factuur is a direct invoice system, it’s not necessary as in Vcom to read first the sales (of all the tables) data in the backoffice and make then an invoice. You can make with “Veft-factuur” direct a invoice of a table. Very popular for Bowling and party centre’s, you can give the customer the invoice direct at the end of the evening.
Account management is done in “Veft-factuur”. Indentification at the ECR can be done with number, scancode, magnetic & chipcard or with an dropdown menu.

veft1
veft2
veft3
veft4
PlayPause
previous arrow
next arrow
 
veft1
veft2
veft3
veft4
previous arrow
next arrow
Vectron Stock

For the Vecton POS system I have build different modules. This is the stock module called “Medium stock”.
With this module you can manage you plu’s, make orders, print barcode labels, check your stock, sales report and more.
It’s the oldest of the modules and has proven itself with various customers.

medium1
medium2
medium3
medium4
medium5
PlayPause
previous arrow
next arrow
 
medium1
medium2
medium3
medium4
medium5
previous arrow
next arrow