While trying to open a chinese camera pen, unfortunately the PCB inside it got damaged. Few of the PCB traces got cut and it became useless. After few days, I removed an 8 pin IC with SO8 package from the PCB. I was curious to know what it is, so I googled the part number 25FW406A but I couldn't find any exact match. I found some part number similar to that and I concluded that it is an SPI flash. Later I got a datasheet from 'ON semiconductor' for a similar part -LE25U40CMD which is a 4M-bit SPI flash memory. I soldered the IC on a common board, powered it with 3.3v and interfaced it to a TI stellaris launchpad via SPI port. According to the datasheet the SPI port need to be initialized in mode 0 or 3. I tried few commands listed in the datasheet and got proper response from the chip, the CHIP ID doesn't matches but that is expected because it is not the same part. I wrote functions for erasing, reading and writing the flash memory and tested it successfully using the launchpad.
Then I thought of making an audio player using this chip which can play 8K mono wav file for around 1 minute. I selected Attiny13 microcontroller for this project. It is always fun to do some thing with limited resources. Attiny13 MCU is having 1KB flash and 64 bytes RAM. Also it is an 8 pin MCU. There are 5 GPIOs. I don't want to change the reset pin as a GPIO because I want to program it via ISP while developing the firmware.
My requirements are,
1> One PWM pin for audio out. [1 pin]
2> SPI pins for interfacing with flash memory. (SO, SI, CS, SCK) [4 pins]
3> UART communication for song update. [2 pins]
4> Switch to select song loading mode [1 pin]
So all together 8 pins are required. But the controller have only 5 GPIOs. Out of this, PB0 is used as PWM for audio out. So I cannot use hardware SPI because PB0 is the MOSI pin for hardware SPI. So no other option, I have to use software SPI but it is not a problem. I used the other 4 pins for SPI. To update song in memory chip, I thought of using UART because it is the most popular way of communication between microcontroller and a PC, also most electronics hobbyist will have one usb to uart converter or an RS232 port and a MAX232 circuit. I used the same PWM pin as UART RX because it is having pin change interrupt feature. Also while flashing wav file, I don't want to use the PWM function. Also it is the only free PIN which is not connected to the SPI port of the memory chip. Now I need a TX pin for sending ACK to the programmer and for proper handshaking while loading the song to memory chip. I used the SCK pin for this purpose. But SCK pin will toggle while communicating with the memory, I don't want this to get coupled into the RX of other end (PC). So I used a mosfet to prevent it. The SCK will toggle only if chip select is LOW and I need to send acknowledgement and do handshaking only when the CHIP SELECT is HIGH. (means when memory chip is not selected or not active). So it made my job easier, I just need to connect the GATE of the n channel mosfet to chipselect pin and the SOURCE to the SCK pin. Now the DRAIN pin is pulled UP using a resistor and is used as a bitbanged TX. Done... Now I need to make a provision to enter into the flash loading mode, so I connected a push button on the same RX pin (or PWM pin - PB0). I made it in such a way that while the button is pressed while powering the circuit, it will enter into flash loading mode. It will never use PWM function in this mode. So always the PB0 pin is an input pin, using PIN change interrupt I implemented the UART receiver. The baudrate of my bitbanged uart is 115200. I wrote a python script on PC side for flashing song into the spi flash. Since the page size of spi flash is 256 bytes and the RAM is only 64 bytes, I am forced to send each byte received on uart to the spi flash. So I am sending the song as 256 byte packet and after every packet I will receive a 1 byte acknowledgement from the mcu. Then I am sending a write token to the MCU without that the mcu will not accept the next 256 bytes. This makes it more reliable, either the complete (max 512) bytes long song will get loaded or will show error in the middle if anything went wrong.
To drive the speaker I used two mosfets as a push pull pair. I used a general purpose n MOS pMOS pair, it can be updated with power mosfets for driving higher wattage speakers. It is a simple class D amplifier. In prototype I didn't used an LC filter, just connected the speaker using a capacitor in series. This is not recommended as it can damage the speaker and will consume extra power because of PWM switching frequency is directly passed through the speaker coil. But we will not be able to hear the high frequency switching noise because it is above the audible range. The recommended method is to use a 2nd-order Butterworth Low-Pass filter (considering the cost and performance) to restrict the signal in the audible range. In my case, I designed it for a cutoff frequency of 8KHz because my wave files are of 8K sampling rate. Also my pwm switching frequency is only 37.5KHz at 9.6MHz internal clock, so it is always better to keep the cutoff frequency far less than the switching frequency to make it more power efficient and to reduce the EMI.
LC filter design:
Cut off frequency = fc = 1/(2*pi*sqrt(LC))
Q factor = R * sqrt(C/L)
R is the speaker impedance , most it will be written on the speaker, say 8E, 4E, 16E etc ... (neglecting the impedance variation of speaker coil on frequency)
Here it will be critically damped if Q value is 0.707, above which it will be underdamped. Too much underdamping is also not recommended. In my case, the Q-factor is around 0.8 and fc is around 8KHz at 8E speaker impedance. As the cutoff frequency increases, the inductor and capacitor values can be reduced. Current rating of inductor is also very important, else the inductor can go to saturation and will result in drastic change at high current.
In my case, the L C R values are 200uH, 2.2uF and 8 ohms.
Firmware and Python wav loader: