TinyPlayer is an IR remote controlled and LiPo battery powered MP3 player based on ATtiny13A and DFPlayerMini module. The DFPlayer module is controlled via a simple cycle-precise software implementation of the UART protocol (8N1, 9600 BAUD) in half-duplex mode. The volume last set as well as the track number last played are saved in the EEPROM and automatically loaded the next time it is started. TinyPlayer has a built-in battery charging circuit, which is supplied with power via a USB-C connector. You can directly connect a 3.7V LiPo battery and a 3W/4Ohm speaker to the board.
- Project Video (Youtube): https://youtu.be/XRpFHvouraQ
- Firmware (Github): https://github.com/wagiminator/ATtiny13-TinyPlayer
## DFPlayer Mini Module
The [DFPLayer Mini module](https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299) is a serial MP3 module that offers the perfect built-in MP3 hardware decoding. It supports TF cards with FAT16 and FAT32 file systems. Music playback as well as other functions can be controlled by simple serial commands without cumbersome software implementation. The main features of the module are easy to use, stable and reliable functions.
## Battery Charger
For battery charging the [MCP73831](https://datasheet.lcsc.com/szlcsc/1809191822_Microchip-Tech-MCP73831T-2ATI-OT_C14879.pdf) is used. The MCP73831 is a highly advanced linear charge management controller for use in space-limited, cost-sensitive applications. It employs a constant-current/constant-voltage charge algorithm with selectable preconditioning and charge termination. The constant current value is set with one external resistor (R6). Charging is done via the built-in USB-C connector.
## User Control
The device is completely controlled via an IR remote control. A [TSOP4838](https://www.vishay.com/docs/82459/tsop48.pdf) is used to receive the IR signals. An [ATtiny13A](http://ww1.microchip.com/downloads/en/DeviceDoc/doc8126.pdf) microcontroller brings it all together.
## UART Fundamentals
UART stands for Universal Asynchronous Receiver Transmitter. It is a serial interface, whereby the data transfer takes place asynchronously (i.e. without its own clock signal). A UART interface has two connections: TxD and RxD (often also referred to as Tx and Rx) and a common ground connection. TxD stands for Transmit Data. From here, data is sent to the communication partner. So the TxD pin acts as an output pin. RxD stands for Receive Data. Data is received from the communication partner from here. So the RxD pin acts as an input pin. The connections of the communication partners are cross-linked, i.e. the TxD output of the first system is connected to the RxD input of the second system and vice versa. Only two partners can be connected to each other using UART.
Since UART data transmission is asynchronous data transfer, there is no clock signal with which the transmitter and receiver can synchronize. Since the UART protocol is a binary baseband signal, the bit rate is the same as the baud rate (symbol rate). The baud rate (transmission speed) must be set identically for both communication partners.
The data transmission via UART takes place with a fixed data frame (UART frame). This must be known to both communication partners. A UART frame consists of:
- a start bit
- 5-9 data bits
- an optional parity bit
- one or two stop bits
The start bit in the UART protocol is required so that the communication partners can synchronize. In the idle state, the UART bus is at logic 1 (HIGH). The start bit is logic 0 (LOW) and signals the start of a UART frame. The start bit is followed by 5 to 9 data bits. These are sent in little-endian format, i.e. the LSB (least significant bit) first. For a "0"-bit the UART bus line ist set to LOW, for a "1"-bit it is set to HIGH. The parity bit is optional. It is used to detect errors. The UART frame is terminated by one or two stop bits. Sometimes an extended stop bit (1.5 stop bits) is also used. Stop bits have the status logical 1 (HIGH).
There is an abbreviated notation for the format of UART frames. 8N1 means: 8 data bits, no parity bit, 1 stop bit. The 8N1 format is often used when transferring data from microcontroller to PC or other devices and is also used here.
## UART Implementation
The implementation is for half-duplex, so it is not possible to send and receive at the same time. It is cycle-accurate due to the use of the delay_cycles function instead of delay_us. The number of MCU clock cycles per UART bit is simply calculated by dividing the MCU clock rate by the UART BAUD rate. By analyzing the compiled and reassembled code, the timing can be determined with an accuracy of a single MCU clock cycle. So here's the initialization part of the UART implementation:
// UART macros
#define UART_TX_setHigh() PORTB |= (1
Collect to album