{"id":323,"date":"2008-02-24T14:03:09","date_gmt":"2008-02-24T13:03:09","guid":{"rendered":"http:\/\/www.evertdekker.com\/wp\/?p=323"},"modified":"2015-08-03T16:02:45","modified_gmt":"2015-08-03T15:02:45","slug":"rc2-decoder-sound-voice-playback","status":"publish","type":"post","link":"https:\/\/evertdekker.com\/wp\/?p=323","title":{"rendered":"RC2 Decoder sound \/ voice playback"},"content":{"rendered":"<hr \/>\n<p><strong>What is it?<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" id=\"__wp-temp-img-id\" title=\"\" src=\"http:\/\/evertdekker.com\/Joomla\/images\/stories\/projects\/RC2%20Decoder\/Rc2_simple.JPG\" alt=\"\" width=\"175\" height=\"97\" \/><\/p>\n<p>It\u2019s an very simple, only 2 resistors and 1 condensator, sound playback. And it sounds amazing good, check the <a href=\"http:\/\/evertdekker.com\/Joomla\/images\/stories\/projects\/RC2%20Decoder\/TheFinalResult.mp3\"><em>TheFinalResult.mp3<\/em><\/a> file.This is based on an article by Mariano Barron in the Circuit Cellar #180 July 2005. Due the copyright I can\u2019t publish the article here. You can buy your copy at the Circuit Cellar website.<br \/>\nThe 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 \u201cSoundcard\u201d\u00a0Every sample requires only 1 bit, so for 1 second 44,1kHz sound we need 2726 Bytes storage space. It\u2019s 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.<\/p>\n<p><strong>Hardware<\/strong><\/p>\n<p><a title=\"\" href=\"http:\/\/evertdekker.com\/Joomla\/mambots\/content\/multithumb\/images\/1.stories.projects.RC2%20Decoder.Schematic.jpg\" target=\"_blank\" rel=\"lightbox[Schematic]\"><img loading=\"lazy\" decoding=\"async\" class=\"multithumb\" title=\"Schematic\" src=\"http:\/\/evertdekker.com\/Joomla\/mambots\/content\/multithumb\/thumbs\/b.150.100.16777215.0.stories.projects.RC2%20Decoder.Schematic.jpg\" alt=\"Schematic\" width=\"228\" height=\"156\" border=\"0\" hspace=\"6\" \/><\/a><\/p>\n<p>Schematic is very simple. I\u2019m 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\u2019t try that.In the upper right corner we have the Rc2 decoder and optional an low pass filter and a simple amplifier.<\/p>\n<p><strong>Timing<\/strong><br \/>\nEven the timer isr calculation is simple Crystal\/prescaler\/sample rate = 16000000\/1\/44100 = 362 = &amp;H016A .<br \/>\nIf you like to use an other sample rate or crystal you need to recalculate the timer.<\/p>\n<p><strong>Diy<\/strong><br \/>\nThe 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.<\/p>\n<p><strong>Limitation<\/strong><br \/>\nIn all the routines are 16bits addressing used, therefore it\u2019s not possible to use Eeprom\u2019s 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\u2019s something that we cannot change.<\/p>\n<p><strong>Required tools<\/strong><\/p>\n<ul>\n<li>Sound edit software, Windows sound recorder will do, but there\u2019s always better<\/li>\n<li>RC Sound encoder <a href=\"ftp:\/\/ftp.circuitcellar.com\/pub\/Circuit_Cellar\/2005\/180\/Barron180.zip\">ftp:\/\/ftp.circuitcellar.com\/pub\/Circuit_Cellar\/2005\/180\/Barron180.zip<\/a><\/li>\n<li>Atmel Avr studio 4 <a href=\"http:\/\/www.atmel.com\/\">www.atmel.com<\/a><\/li>\n<li>I2C Eeprom programmer including software or <a href=\"http:\/\/www.evertdekker.com\/wp\/?p=321\">my programmer<\/a> written in Bascom<\/li>\n<li>DIY <a href=\"http:\/\/evertdekker.com\/Joomla\/images\/stories\/Downloads\/2RC-Diy.ZIP\">Do it yourself package<\/a>\u00a0 incl. Bascom source code, used WAV samples and DIY.pdf<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><strong>The code<\/strong><br \/>\nCode is written and tested in Bascom 1.11.9.0.001 license.<\/p>\n<pre class=\"brush: vb; gutter: true\">&#039;------------------------------------------------------------------\r\n&#039;                      R2C Decoder voice playback\r\n&#039;     Playback sound and voice with very simple hardware 2xR 1xC\r\n&#039;        By Evert Dekker 2008 R2CDecoder@Evertdekker dotje com\r\n&#039;                   Created with Bascom-Avr: 1.11.9.0.100\r\n&#039;------------------------------------------------------------------\r\n\r\n$regfile = &quot;m128def.DAT&quot;\r\n$crystal = 16000000\r\n$baud = 19200\r\n$hwstack = 50\r\n$swstack = 50\r\n$framesize = 40\r\n\r\n$lib &quot;I2C_TWI.LBX&quot;                                          &#039;Setting up i2c hardware bus\r\nConfig Twi = 400000                                         &#039;Hardware i2c bus speed\r\nConfig Scl = Portd.0                                        &#039;TWI (i2c) ports on the Mega128\r\nConfig Sda = Portd.1\r\nConst Addressw = &amp;B10100000                                 &#039;slave write address eeprom\r\nConst Addressr = &amp;B10100001                                 &#039;slave read address eeprom\r\n\r\n\r\nVp1 Alias Porta.1                                           &#039;Voice pin 1\r\nVp2 Alias Porta.2                                           &#039;Voice pin 2\r\nConfig Porta.1 = Output\r\nConfig Porta.2 = Output\r\n\r\n\r\nConfig Timer1 = Timer , Prescale = 1 , Compare A = Set , Clear Timer = 1       &#039;Setting up the timer\r\nCompare1a = &amp;H016A                                          &#039;Timer1 comparator\r\nEnable Interrupts\r\nEnable Compare1a\r\nOn Compare1a Timer1_int\r\nStop Timer1                                                 &#039;Stop the timer, not yet needed\r\n\r\n\r\n&#039;==== Declaration\r\nDeclare Sub Read_eeprom_word(byval Adress As Word , Valueword As Word)\r\nDeclare Sub Playsample(byval Sample As Byte)\r\nDeclare Sub Read_eeprom_index\r\n\r\nDim Samples As Word , Start_byte(10) As Word , Lenght(10) As Word       &#039;If you have more then 10 voices programmed, then incr this here.\r\nDim Bytetodo As Word , Outbyte As Byte\r\nDim Temp As Byte , Tempw As Word , Lus As Byte\r\nDim Bitcount As Byte , Tempadress2 As Byte\r\n\r\n&#039;=== Main ===\r\nDo\r\nRead_eeprom_index                                           &#039;Read the eeprom index because we need to know number of samples, startadress and lenght\r\nPrint Samples ; &quot; Samples present in the eeprom&quot;\r\nFor Lus = 1 To Samples\r\n Print Lus ; &quot;e sample start at eeprom adress: &amp;H&quot; ; Hex(start_byte(lus)) ; &quot; is &amp;H&quot; ; Hex(lenght(lus)) ; &quot; bytes long.&quot;\r\nNext For\r\nWait 3\r\n\r\nFor Lus = 1 To Samples\r\n Playsample Lus\r\nWait 1\r\nNext Lus\r\n\r\nLoop\r\nEnd\r\n\r\n\r\n\r\n&#039;=== Sub routines ===\r\nSub Playsample(byval Sample As Byte)\r\nBytetodo = Lenght(sample)                                   &#039;Number of bytes to be processed\r\nTempw = Start_byte(sample) * 2                              &#039;Index is in word, need now bytes so *2\r\nI2cstart                                                    &#039;Generate start\r\nI2cwbyte Addressw\r\nTempadress2 = High(tempw)                                   &#039;High(adress)\r\nI2cwbyte Tempadress2                                        &#039;highbyte adress of EEPROM\r\nTempadress2 = Low(tempw)\r\nI2cwbyte Tempadress2                                        &#039;lowbyte adress of EEPROM\r\nI2cstart                                                    &#039;repeated start\r\nI2cwbyte Addressr\r\nStart Timer1                                                &#039;Start the timer and therefore the playback\r\nDo\r\nIf Bitcount = 7 Then                                        &#039;1 byte processed\r\n   I2crbyte Outbyte , Ack                                   &#039;Read byte from eeprom\r\n    Decr Bytetodo                                           &#039;1 byte less todo\r\n    Bitcount = 0                                            &#039;Reset bits processed\r\nEnd If\r\nLoop Until Bytetodo = 0                                     &#039;Do until all the bytes from the sample are processed\r\nStop Timer1                                                 &#039;Ready stop the timer\r\nI2crbyte Temp , Nack                                        &#039;read extra byte with Nack to finish the i2c bus\r\nI2cstop                                                     &#039;Stop i2c\r\nVp2 = 0 : Vp1 = 0                                           &#039;Silence the voice pins\r\nEnd Sub\r\n\r\n\r\n\r\nTimer1_int:\r\nVp2 = Vp1                                                   &#039;Voice pin2 is the previous setting of voice pin1\r\nIf Bitcount &gt; 0 Then Shift Outbyte , Right , 1              &#039;shift the bits out\r\nVp1 = Outbyte.0                                             &#039;Set voice pin1\r\nIncr Bitcount                                               &#039;Next bit\r\nReturn\r\n\r\n\r\n\r\nSub Read_eeprom_index                                       &#039;Find the start adresse of each Voice. Adress is stored as word\r\n      Read_eeprom_word 0 , Samples                          &#039;1e Byte in the eeprom contens the number of programmed samples and is the low byte of the first sample\r\n      Temp = Low(samples) : Temp = Temp -1                  &#039;\r\n      For Lus = 0 To Temp                                   &#039;Loop the number of Samples found\r\n          Tempw = Lus * 2                                   &#039;Reading words, so steps 2\r\n          Read_eeprom_word Tempw , Start_byte(lus + 1)      &#039;Read the start adres of the samples\r\n          Tempw = Start_byte(lus + 1)\r\n          Tempw = Tempw * 2                                 &#039;Reading words, so steps 2\r\n          Read_eeprom_word Tempw , Lenght(lus + 1)          &#039;Read the lenght of the sample from the eeprom\r\n          Rotate Lenght(lus + 1) , Left , 8                 &#039;Msb and Lsb are inverted so swap them\r\n      Next Lus\r\nEnd Sub\r\n\r\n\r\n\r\n\r\nSub Read_eeprom_word(byval Adress As Word , Valueword As Word)\r\n   Local Tempadress As Byte , Valueh As Byte , Valuel As Byte,\r\n   I2cstart                                                 &#039;generate start\r\n   I2cwbyte Addressw                                        &#039;slave adsress\r\n   Tempadress = High(adress)\r\n   I2cwbyte Tempadress                                      &#039;highbyte adress of EEPROM\r\n   Tempadress = Low(adress)\r\n   I2cwbyte Tempadress                                      &#039;lowbyte adress of EEPROM\r\n   I2cstart                                                 &#039;repeated start\r\n   I2cwbyte Addressr                                        &#039;slave address (read)\r\n   I2crbyte Valuel , Ack                                    &#039;read byte\r\n   I2crbyte Valueh , Nack\r\n   I2cstop                                                  &#039;generate stop\r\n   Valueword = Makeint(valuel , Valueh)\r\nEnd Sub<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What is it? It\u2019s 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\u2019t publish the article here. You can buy your copy at the [&#8230;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[26,41,40],"class_list":["post-323","post","type-post","status-publish","format-standard","hentry","category-bascom","tag-bascom","tag-sound-playback","tag-voice-playback"],"_links":{"self":[{"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/323","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=323"}],"version-history":[{"count":10,"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/323\/revisions"}],"predecessor-version":[{"id":333,"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/323\/revisions\/333"}],"wp:attachment":[{"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=323"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/evertdekker.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}