
The chosen microcontroller was the PIC12F1840. It was chosen because of its fast clock rate (up to 32 MHz). Since microchip PICs have this atrocious property of executing one instruction every four clock cycles, this results in 8MIPS performance. The second reason for the choice was the hardware SPI module - bit-banging SPI is not hard, BUT doing it fast enough to sustain the sound playback would be - the hardware SPI module helps by allowing the SPI clock to be as high at 8MHz without using nearly as much CPU time as bit-banging would. The reset of the circuit design was easy: the PIC outputs a PWM waveform to drive the speaker, which is amplified by a MOSFET, PIC's SPI controller talks to the SD card, and another GPIO is used to provide power to te SD card allowing it to be powered off and thus letting the circuit sleep in very low power mode (nanowatts of power used). The pic is overclocked using the OSCTUNE register to 33MHz from the stock speed of 32MHz.
The SD card driver is my own work, and supports SD/MMC/SDHC/RS-MMC/HS-MMC/miniSD/microSD/transFlash and whatever others are in that family. Card is initialized at 375KHz (which is within spec), and then the bus is clocked at 8MHz for data reads/writes. The driver is peculiar for a few reasons, mainly because it does not try to be an abstraction between the SPI bus and the caller, thus the driver will init the card, and set it up to stream sectors to the caller. The caller then calls spiByte() directly to read sector data. Every 512 calls, a call to sdNextSector() is needed to notify the SD driver that we want the next sector & properly wait for it to start.
Since there is some time between the end of streaming of one sector and beginning of streaming the other, buffering is used for audio data. The buffer is a simple circular buffer that the audio thread reads from, and the SD thread writes to. When buffer is full, SD thread busy-waits for a slot to open to write data into. Since SD cards do not care how much time passes between clock ticks, this wait can be as long as needed.

The random number geneartor used is a very simple 32-bit multiplication-addition-modulus type, where Xn = (Xn-1 * 0xDEECE66D + 0x0B) % 0x100000000. The seed is stored in the last 4 bytes of EEPROM, so that on each power-on the sequence of sonds is not repated, but continued from the last time. The top 16 bits of the modified seed are returned as the "random" number to the caller.
Given all of the above, the method of operation becomes simple:
Power on SD card
Init SD card
List files in root directory
Count number of non-hidden files with "WAV" extension
Loop:
Select a file randomly
Use uFAT to find the sector extents file occupies (fragmentation is properly handled)
Store those sectors in the sectorList storage
Init audio playback
Play data from sectors in each extent until there is no more
turn audio off
enter low power sleep for a determined time (30 sec currently, random length in the future)
power card on
[Re-] init card
Detailed PIC resource usage:
Clocks: 33MHz when playing, 500KHz when waking from sleep before deciding to sleep more
WDT: Used to wake from sleep
Reference Clock Module: Unused
Interrupts: Timer0 overflow interrupt used, others unused
Data EEPROM: 4 bytes at end used, others unused
Program Flash: Code uses 40%, sectorList uses 45%
GPIOs: 3 used for SPI, 1 used for output, 1 used for SD card power control. RA3 unused.
Fixed VoltageReference: Unused
Temperature indicator: Unused
ADC: Unused
DAC: Unused
SR Latch: Unused
Comparator: Unused
Timer0: Used for sound playback timing, overflows 22050 times a second, with proper reload value
Timer1: Unused
Timer2: Used for PWM module's timing
Data Signal Modulator: Unused
PWM: used to produce output sound
MSSP: used in SPI master mode to talk to the SD card
EUSART: Unused
Capacitative Sensing Module: Unused
As can be seen in the video here, it all works rather well. To address a few final questions: Audio files are uncompressed WAV files. The cde attempts to figure out the specific format and play nice with it, but 8 bit samples work best. SD card must be formatted FAT16 since uFAT does not support FAT12 or FAT32. This may (and likely will) change in the future. The maximum number of file fragments is set in the code, and is something like 128 currently, any more than that will not be played, or will cause data corruption, so defragment your card sometimes, if you plan to replace sound files often. Code cleanup is on the way, and the code will be released after cleanup is complete. For now, here's the HEX file for the PIC12F1840: [DOWNLOAD]. Source (current snapshot) can be downloaded [HERE]
No comments:
Post a Comment