Difference between revisions of "S16: Sound Buddy"

From Embedded Systems Learning Academy
Jump to: navigation, search
(References)
 
(307 intermediate revisions by the same user not shown)
Line 1: Line 1:
=== Grading Criteria ===
 
<font color="green">
 
*  How well is Software & Hardware Design described?
 
*  How well can this report be used to reproduce this project?
 
*  Code Quality
 
*  Overall Report Quality:
 
**  Software Block Diagrams
 
**  Hardware Block Diagrams
 
**:  Schematic Quality
 
**  Quality of technical challenges and solutions adopted.
 
</font>
 
 
 
== Project Title ==
 
== Project Title ==
=== Sound Buddy ===
+
[[File:CMPE244 SP16_Sound_Buddy_Logo_1.jpg|600px|center]]
  
 
== Abstract ==
 
== Abstract ==
This section should be a couple lines to describe what your project does.
+
You turn up your music to rock out to but you forget your dancing shades in the other room so you run to the other room to look for it and by the time you find it your favorite part has already passed. Now, you have to start the song all over again.
 +
 
 +
What a bummer!
  
Sound Buddy is a portable, wireless speaker system designed to play MP3 encoded sound. Load MP3 audio onto an SD card and plug it into the controller box. A Nordic wireless transmitter will wirelessly transmit the file to two receivers. Each receiver will send the file over SPI communication to an MP3 decode board. The MP3 decode boards will decode and convert the file to analog and send it to a speaker.
+
Sound Buddy is an affordable wireless speaker system designed to play your favorite music in any room you are walking into or every room. Load your favorite MP3 songs onto a micro SD card and plug it into Sound Buddy. Place the Sound Buddy speakers in any room, and you are ready. You can jam out to your favorite song and if you forget your favorite dancing shades again, Sound Buddy will switch the speaker in another room to blast your song. You will never miss your favorite part again!
  
== Objectives & Introduction ==
+
Developed with amazing technologies such as the Nordic transceiver device, MP3 decoder, SJOne board, and the powerful FreeRTOS, Sound Buddy comes to life!
Show list of your objectives.  This section includes the high level details of your project.  You can write about the various sensors or peripherals you used to get your project completed.
 
  
 +
Walk through the design and development of the prototype for this exciting project.
  
Sound Buddy can be broken down into four main efforts: reading the MP3 file, formatting and sending the MP3 over Nordic wireless, receiving the MP3, decoding the MP3 to audio.  
+
== Objectives ==
 +
The implementation of Sound Buddy can be broken down into four main efforts.
  
 
'''Reading the MP3 File'''
 
'''Reading the MP3 File'''
The MP3 file is read from the SD card on the SJSU ONE board.  
+
The MP3 file is read from a loaded mircoSD card to the SJSU-ONE board's flash memory.  
  
 
'''Converting and Sending MP3 over Nordic Wireless'''
 
'''Converting and Sending MP3 over Nordic Wireless'''
The MP3 file is formatted for Nordic wireless transmission. Then sent to two SJSU ONE boards.  
+
The MP3 is wirelessly sent from the Sender-board's flash memory to the Receiver-boards' flash memory.  
  
 
'''Receiving MP3 Files'''
 
'''Receiving MP3 Files'''
The receiver boards receive the files and prepare them for transmission over an I2C bus to the MP3 decode board.
+
The Receiver-boards receive the MP3 file and prepare the MP3 file for transmission over an I2C communication bus to the MP3 decoder board.
  
 
'''Decoding MP3 to Audio'''
 
'''Decoding MP3 to Audio'''
The decode boards receive the files over the SPI communication link, then reformat the file to standard MP3 and decode it to analog.  
+
The decoder board receives the file over the SPI communication bus and reformats the file to send raw data to the DAC where the speakers will be connected.
 
 
  
=== Team Members & Responsibilities ===
+
=== Team Members - Responsibilities ===
*  Brigitte De Leon
+
[https://www.linkedin.com/in/brigittedeleon Brigitte De Leon] - Tell everyone what to do
*Nordic Wireless
+
Catherine Gamboa - Be early to all the meetings
Catherine Gamboa
+
Hudo Assenco    - Wake up
*PCB Design/Delivery
+
Yang Thao        - Buy everything
  
Hudo Assenco
+
The team members worked closely together every weekend of their hectic lives in the spring semester of 2016 to produce a beating heart for this project. Brigitte and Hudo worked on the Nordic wireless device code to get the data sent from one board to another in a streaming fashion. Catherine and Yang worked on the MP3 decoder circuit to be able to properly decode the MP3 file from the SJ-One board. Hudo and Catherine designed the PCB board that houses the MP3 decoder circuit. Yang made sure to supply the team with all of the material and then some. Brigitte brought the team together and kept the vision alive. Everyone put in time and effort to keep the Wiki document up-to-date through the duration of the project. Each sub team ran their own tests to assure that the subsystems were working as designed. The integration tests and debugging were tackled by all the members.
**  Integration Master
 
Yang Thao
 
** MP3 Decoder
 
  
 
== Schedule ==
 
== Schedule ==
Show a simple table or figures that show your scheduled as planned before you started working on the project.  Then in another table column, write down the actual schedule so that readers can see the planned vs. actual goals.  The point of the schedule is for readers to assess how to pace themselves if they are doing a similar project.
 
 
 
{| class="wikitable" style="width: 90%; height: 40%;"
 
{| class="wikitable" style="width: 90%; height: 40%;"
 
|-
 
|-
Line 72: Line 57:
 
! style="text-align: center;"| 03.28
 
! style="text-align: center;"| 03.28
 
| <li>Order PCB<li>Develop Nordic communication protocol<li>Write code to allow Nordic wireless communication between two boards<li>Update Wiki
 
| <li>Order PCB<li>Develop Nordic communication protocol<li>Write code to allow Nordic wireless communication between two boards<li>Update Wiki
| <li>In Progress
+
| <li>PCBs received <li>Completed
 
|-
 
|-
 
! scope="row"| 4
 
! scope="row"| 4
 
! style="text-align: center;"| 04.04
 
! style="text-align: center;"| 04.04
| <li>Build MP3 decoder prototype circuit and verify its functionality<li>Update Wiki
+
| <li>Build MP3 decoder prototype circuit and verify its functionality<li>Verify the Nordic wireless data transfer code works<li>Update Wiki
| <li>Incomplete
+
| <li>Completed
 
|-
 
|-
 
! scope="row"| 5
 
! scope="row"| 5
 
! style="text-align: center;"| 04.11
 
! style="text-align: center;"| 04.11
 
| <li>Load small MP3 into SD card and send out to MP3 decoder to hear audio<li>Update Wiki
 
| <li>Load small MP3 into SD card and send out to MP3 decoder to hear audio<li>Update Wiki
| <li>Incomplete
+
| <li>Completed.<li>Debugging MP3 Decoder prototype<li>Test Nordic wireless mesh commands<li>Solder ICs onto the PCBs
 
|-
 
|-
 
! scope="row"| 6
 
! scope="row"| 6
 
! style="text-align: center;"| 04.18
 
! style="text-align: center;"| 04.18
 
| <li>Integrate the system (SD from Master -> Nordic Wireless -> Flash -> MP3 decoder circuit -> Speakers)<li>Update Wiki
 
| <li>Integrate the system (SD from Master -> Nordic Wireless -> Flash -> MP3 decoder circuit -> Speakers)<li>Update Wiki
| <li>Incomplete
+
| <li>Delayed progress...<li>Debugging MP3 Decoder prototype<li>Updating Nordic wireless class to remove delays<li>Send a file from one board to another with Nordic<li>Continue to solder ICs onto the PCBs
 
|-
 
|-
 
! scope="row"| 7
 
! scope="row"| 7
 
! style="text-align: center;"| 04.25
 
! style="text-align: center;"| 04.25
 
| <li>Solder parts onto PCB<li>Integrate into test system<li>Update Wiki
 
| <li>Solder parts onto PCB<li>Integrate into test system<li>Update Wiki
| <li>Incomplete
+
| <li>Completed<li>Debugging MP3 Decoder prototype<li>Updating Nordic wireless class to send single byte
 
|-
 
|-
 
! scope="row"| 8
 
! scope="row"| 8
 
! style="text-align: center;"| 05.02
 
! style="text-align: center;"| 05.02
 
| <li>Integration test<li>Update Wiki
 
| <li>Integration test<li>Update Wiki
| <li>Incomplete
+
| <li>Delayed progress...<li>Developed Nordic code to send a file to another board<li>Debugging MP3 Decoder prototype
 
|-
 
|-
 
! scope="row"| 9
 
! scope="row"| 9
 
! style="text-align: center;"| 05.09
 
! style="text-align: center;"| 05.09
 
| <li>System test<li>Update Wiki
 
| <li>System test<li>Update Wiki
| <li>Incomplete
+
| <li>Delayed progress...<li>Optimizing Nordic code to send a file to another board<li>Debugging MP3 Decoder prototype
 
|-
 
|-
 
! scope="row"| 10
 
! scope="row"| 10
 
! style="text-align: center;"| 05.16
 
! style="text-align: center;"| 05.16
| <li>Run final tests<li>Prepare for DEMO --> 05.20
+
| <li>Run final tests<li>Prepare for DEMO --> 05.24
| <li>Incomplete
+
| <li>Integration<li>PANIC!...JK<li>Completion of project's phase one
 
|}
 
|}
  
 
== Parts List & Cost ==
 
== Parts List & Cost ==
 +
The parts tabulated below are those necessary to complete the project. It does not reflect the acutal parts used during testing also. During testing, extra devices were used to debug and replace damaged devices. Those dead components lay peacefully in our project graveyard.
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 131: Line 117:
 
| $5.94
 
| $5.94
 
|-
 
|-
! scope="row"| 3
+
! scope="row"| 2
 
| Audio Jack 3.5mm
 
| Audio Jack 3.5mm
| 3
+
| 2
 
| $1.50
 
| $1.50
 
| $4.50
 
| $4.50
Line 139: Line 125:
 
! scope="row"| 4
 
! scope="row"| 4
 
| Crystal 14.7456MHz
 
| Crystal 14.7456MHz
| 5
+
| 2
 
| $0.95
 
| $0.95
| $4.75
+
| $1.90
 
|-
 
|-
 
! scope="row"| 5
 
! scope="row"| 5
 
| Printed Circuit Boards
 
| Printed Circuit Boards
 
| 2
 
| 2
| $-.--
+
| $--.--
| $-.--
+
| $32.05
 
|-
 
|-
 
! scope="row"| 6
 
! scope="row"| 6
Line 169: Line 155:
 
! scope="row"| 9
 
! scope="row"| 9
 
| Screw Terminals 3.5mm Pitch(2-Pin)
 
| Screw Terminals 3.5mm Pitch(2-Pin)
| 3
+
| 4
 
| $0.95
 
| $0.95
| $2.85
+
| $3.80
 
|-
 
|-
 
! scope="row"| 10
 
! scope="row"| 10
 
| Antennas
 
| Antennas
| 2
+
| 3
| $--
+
| $4.20
| $--
+
| $12.60
 
|-
 
|-
 
! scope="row"| 11
 
! scope="row"| 11
 
| Resistors
 
| Resistors
| #
+
| 20
| $---
+
| $0.19
| $---
+
| $3.80
 
|-
 
|-
 
! scope="row"| 12
 
! scope="row"| 12
 
| Capacitors
 
| Capacitors
| #
+
| 120
| $----
+
| $--.--
| $----
+
| $20.11
 
|-
 
|-
 
! scope="row"| 13
 
! scope="row"| 13
 
|Inductors
 
|Inductors
 
| 2
 
| 2
| $----
+
| $0.19
| $----
+
| $0.38
 
|-
 
|-
 
! scope="row"| 14
 
! scope="row"| 14
 
| Voltage Regulators
 
| Voltage Regulators
 
| 2
 
| 2
| $----
+
| $0.62
| $----
+
| $1.24
 
|-
 
|-
 
! scope="row"| 15
 
! scope="row"| 15
 +
| LEDs
 +
| 8
 +
| $0.20
 +
| $1.60
 +
|-
 +
! scope="row"| 16
 
| SJOne Board
 
| SJOne Board
 
| 3
 
| 3
 
| $80.00
 
| $80.00
 
| $240.00
 
| $240.00
 +
|-
 +
! scope="row"| 17
 +
| 9V batteries
 +
| 2
 +
| $-.--
 +
| $8.00
 
|-
 
|-
 
! scope="row"|  
 
! scope="row"|  
Line 213: Line 211:
 
|   
 
|   
 
| $-.--
 
| $-.--
| $-.--
+
| $373.11
 
|-
 
|-
 
|}
 
|}
  
 
== Design & Implementation ==
 
== Design & Implementation ==
The design section can go over your hardware and software design.  Organize this section using sub-sections that go over your design and implementation.
+
The following sections will walk you through the system design and dive into the implementation of Sound Buddy.  
  
 +
After reading through the sections, you'll be able to understand what makes up Sound Buddy's beating heart.
  
<br>
+
=== Hardware Design ===
===The Top Level of Sound Buddy===
 
  
<br>
+
The hardware design was limited by the pins that the SJOne board provided. Luckily, this was not an issue for Sound Buddy. The protocols used were SPI/SSP and I2C so the number of pins were already availble for use of communication. A PCB was designed to house the MP3 decoder circuit. This PCB is mounted right on top of the SJOne board enclosing the unit as one functional device.
  
[[File:Sound Buddy Top Level.jpg]]
+
==== System Design ====
 +
{|
 +
|-
 +
| [[File:CMPE244 S16 Sound Buddy System Design.jpg|400px|left|thumb]]
 +
| Sound Buddy's core component is the SJOne board. For more information about the SJOne board click this link <span class="plainlinks">[http://www.socialledge.com/sjsu/index.php?title=SJ_One_Board SJOne board]</span> or visit the main page of this Wiki.
  
===The Master Board===
+
Its system is composed of a sender device and one or more receiver devices. An MP3 file will be stored on the micro SD card which will be inserted into the sender's SD slot. The sender device will read and send out the raw MP3 data over the Nordic wireless protocol. Each device uses the built-in Nordic wireless transceiver which allows for one-way communication from the sender to the receiver(s).
  
[[File:SJSU ONE Board.jpg]]
+
Plugged onto each on the other receivers is the MP3 decoder circuit. The receiver device will be waiting for the MP3 data. Once it detects data has been sent over, it begins to process the data by sending it out to the MP3 decoder. The MP3 decoder translates the raw data and sends it out to the onboard DAC. The DAC converts the raw data into audible signals that get pushed out to the audio0 jack where the speakers play the music.  
  
===The Receiver Board===
+
Now, that was a mouthful. Let's dive deeper into each of the component design.
 +
|}
  
[[File:Receiver Board.jpg]]
+
<br><br>
  
===The Decode Board===
+
==== Sender Board ====
 +
{|
 +
|-
 +
| The sender board uses the SD card and the [https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf Nordic wireless transceiver] onboard. Using the SPI protocol, the SD card will be enabled for I/O purposes. There is a total of four wires utilized namely the SCK, MOSI, MISO, and CS. These wires are connected internally and the data transfer and chip select are handled by the driver and application code.
  
[[File:Decode Board.jpg]]
+
Similar to the SD card, the Nordic transceiver uses SPI protocol to send and receive data. This, too, is hooked up internally and the initialization and function are done through coding. The additional hardware part attached to the SJOne board is the 2.4GHz Duck Antenna RP-SMA to support the Nordic wireless data transfer. The Nordic data transfer can be sent on an on-air data rate of 250 kbps, 1Mbs, or 2Mbps depending on configuration. It has a maximum speed of 10Mbps on the SPI line and 3 separate 32 bytes TX and RX FIFO. On page 21 of the Nordic nrf24l01+ datasheet, the state diagram from communication can be found. Standby-II mode was used because it was determined to produce the fastest data transfer speed. If the TX FIFO detects a data packet uploaded, then the PLL starts and transmits immediately after PLL delay. To drive the Nordic device, the nrf24L01Plus class (included in the SJOne FreeRTOS project) was used to build a driver class. The driver simply checked if whether the TX FIFO is full and if it's not, data will be sent. It uses a polling method to achieve this.
  
 +
And, that is it for the sender device! Let's move on to the receiver device.
 +
| [[File:CMPE244 S16 Sound Buddy Master Board.png|350px|right|thumb]]
 +
|}
  
The decode board is a custom board whose function is to receive raw MP3 formatted data and decode it for digital to analog conversion.
+
==== Receiver Board ====
 +
{|
 +
|-
 +
| [[File:CMPE244 S16 Sound Buddy Receiver Board.png|600px|left|thumb]]
 +
| The design of the receiver board is very similar to the sender board. Since its microcontroller is also the SJOne board, the onboard Nordic wireless transceiver and SD card slot were used for data transfer and storage. The raw data is sent over the Nordic wireless communication at about 200KBps even though it was able to send data at 1MBps. This is due to the write limitation that the available microSD cards imposed. The pins on the board for the SPI protocol are the same as those indicated in the sender board. A chip select pin was needed to enable the MP3 decoder. A GPIO pin from the SJOne board was configured for that purpose. The MP3 decoder board is connected on top of the SJOne board. The MP3 decoder shares the same SSP1 lines as the SD card. The software controls where the data transfer occurs. The MP3 decoder, also, utilizes the I2C protocol for initialization. The MP3 decoder circuit will be dissected later. Lastly, a speaker with an AUX port is attached to the MP3 decoder.
 +
|}
  
 +
==== MP3 Decoder ====
 +
This circuit is based on the [https://www.pjrc.com/mp3/sta013.html#config tutorial] that details how to use the STA013 chip. The MP3 decoder circuit uses an STA013 MP3 decoder chip to translate raw MP3 data to audible data. A detailed data sheet can be found at [https://www.pjrc.com/mp3/sta013.html STA013 MP3 Decoder].
 +
We used the standard configuration suggested by the manufacturer which recommends that all of the voltage sources higher than 3.3V be brought down to 3.3V to safely operate the device. Since the voltage supply from the SJOne board is 3.3V, this was not an issue.
  
[[File:Decode Board Top Level.jpg]]
+
For the data coming out of the MP3 decoder to produce music through speakers, the [https://www.cirrus.com/en/pubs/proDatasheet/CS4334-5-8-9_F6.pdf CS4334 DAC] is used. This chip operates on a 5V supply so the SJOne board could not be used as a source. Instead, a 9V battery is used to supply the power. A 5V regulator circuit using a [https://www.sparkfun.com/datasheets/Components/LM7805.pdf 7805 voltage regulator] was built to step down the voltage level supply to prevent damage to the DAC device.
  
=== Hardware Design ===
+
An audio jack is tied to the output of the DAC device to send music out to speakers with an auxiliary port. The speakers are powered internally with a rechargeable baterry. Any off-the-shelf speaker can be transformed into a Sound Buddy receiver.  
Discuss your hardware design here. Show detailed schematics, and the interface here.
 
  
[[File:Decode Brd Schematic.jpg]]
 
  
The Master board and receiver boards are SJSU ONE boards used in standard configurations.  
+
[[File:CMPE244 S16 Sound Buddy MP3 Decoder Board.png|800px|left|thumb]]
 +
Some assumptions are made about the usage of the STA013 device according to the tutorial. To summarize, for "normal" usage, its assumed that the STA013 will run off multimedia mode. The device will detect the MP3 data's bitrate and will send a signal that requesting for data. Data is fed to the STA013 up to 20Mbit/sec. The correct clock and data out to the DAC is also handled by the device. The STA013 will be driving the DAC and the output clock to synchronize with it. Since the tutorial uses a Cs4334 DAC chip in conjunction with a 14.7456 MHz crystal, those devices were used in the MP3 decoder as well. The DAC was chose due to it being inexpensive and its ability to output audio without noise.
 +
<br>
 +
<br>
 +
<br>
 +
<br>
 +
<br>
 +
<br>
 +
<br>
 +
<br>
 +
<br>
 +
<br>
 +
The following is an illustration of the circuit described in the STA013 tutorial. Each significant portion of the circuit is boxed and labeled.
 +
[[File:CMPE244 S16 Sound Buddy MP3 Decoder Schematic.png]]
 +
<br>
 +
<br>
 +
<br>
 +
To package the MP3 decoder circuit nicely, a PCB was designed and printed to house the circuit. [https://learn.sparkfun.com/tutorials/how-to-install-and-setup-eagle EAGLE PCB] software was used to design the board layout. [https://oshpark.com/ OSH Park] was used to print the boards since the supply location was location locally in the Silicon Valley and the cost was affordable.
  
The Decode board is a custom build PCB. The Decode board consists of three functions: MP3 Decode, DAC, and Voltage Regulator, as well as a 34 pin connector.
+
LEDs were added in pins for enable and data signals to assist with debugging to assure that the MP3 was functioning as designed.
 +
<br>
 +
{|
 +
|-
 +
| [[File:CMPE244 S16 SoundBuddy PCB layers.png|500px|left]]
 +
| The illustration on the left is the layout the devices and interconnections on the board. It showcases both the top and bottom layers. The components were positioned with the thought of ease during the soldering of the devices and accessiblitity of the pins and ports.
 +
<br>
 +
<br>
 +
To the right are the images of the top and bottom of the expected layouts of the board. The PCB was designed to fit snuggly on top of the SJOne board. The pins on the right of the board align right on top the SJOne board's I/O pins to allow for accessibility.
 +
| [[File:CMPE244 S16 SoundBuddy PCB Top Bottom.png|300px|right]]
 +
|}
  
'''MP3 Decode'''
+
=== Software Design ===
 +
The software design is separated by three different components that make up the Sound Buddy system. These components are the sender, receiver, and MP3 decoder. Each required a driver to be implemented to get the subsystems functioning properly.
 +
==== Sender Board ====
 +
The sender board was designed to initialize the necessary device drivers (SPI/SSP & Nordic wireless) and run FreeRTOS. The tasks created were used to read data from the SD card to the RAM and from the RAM, send the data to the Nordic wireless device. There were two tasks created, one to read from the SD card and another to write to SPI bus out the Nordic wireless device.
 
<br>
 
<br>
The MP3 Decode board uses a STA013 MP3 Decoder chip. A detailed data sheet can be found at: [https://www.pjrc.com/mp3/sta013.html STA013 MP3 Decoder]
 
  
We used the standard configuration suggested by the manufacturer. The manufacturer suggests all signals from 5 volt boards and all 5 volt supplies be stepped down to 3 volts. Since the signals from the SJSU ONE board are in the 3 volt range, and power is supplied by the SJSU ONE board, we did not have to implement the any voltage step downs.  
+
[[File:CMPE244 S16 Sound Buddy SendTask.png]]
  
 
<br>
 
<br>
'''DAC'''
+
 
 +
==== Receiver Board ====
 +
The receiver board also initializes the necessary device drivers (SPI/SSP & Nordic wireless) and run FreeRTOS. It also depends primarily on two tasks. One task to wait for the RX FIFO to receive a data packet and the send task to handle the writing to the SD card. As soon as the MP3 file is completely loaded into the SD card, it waits for a command to be sent to control the MP3 decoder functionality.
 +
 
 +
[[File:CMPE244 S16 Sound Buddy ReceiveTask.png]]
 +
 
 +
==== MP3 Decoder ====
 +
The [https://www.pjrc.com/mp3/sta013.html#config tutorial] describes the configuration and use of the STA013 MP3 decoder chip. The basic configuration and data transmit are depicted in the flowchart below.
 +
<br>
 +
 
 +
[[File:CMPE244 S16 Sound Buddy MP3 Decoder Flow.png‎ ]]
 +
 
 
<br>
 
<br>
The DAC chosen for this design is the CS4334, which is the one recommended by the MP3 Decode manufacturer. A detailed data sheet can be found at: [https://www.pjrc.com/mp3/sta013.html CS4334 DAC]
+
 
The speakers are battery powered, so the connection to the speakers does not require power.
+
With an I2C address of 0x86, communicating to the MP3 decoder chip was simple after configuration. The SJOne board's code base includes an I2C driver that helped drive the communication.
 +
When you start feeding in valid MP3 data, the chip detects the MP3 sample rate and creates the correct clock for the DAC and starts pushing data into it.  
 +
The STA013 will ignore non-MP3 data so it is safe to send the entire file without needing to strip out ID3 tags, etc.
 +
The STA013 expects the most significant bit first, which corresponds to the SPI standard.
  
 
<br>
 
<br>
'''Voltage Regulator'''
+
 
 +
=== Hardware Implementation ===
 +
==== Sender & Receiver Board ====
 +
The following image is of the entire Sound Buddy system which includes the sender, receiver, and MP3 decoder board. The board in the middle is the sender board which is connected to the laptop to access the interface. The off-the-shelf speakers are connected to receiver boards.
 
<br>
 
<br>
The voltage regulator chosen for this board is the LM7805, configured using the standard application configuration. A detailed data sheet can be found at: [https://www.fairchildsemi.com/datasheets/LM/LM7805.pdf LM7805 Voltage Regulator]
+
{|
 +
|-
 +
| [[File:CMPE244 S16 Sound Buddy System ALL.png|600px]]
 +
|                             
 +
|
 +
|     
 +
|
 +
|
 +
|
 +
|
 +
| [[File:CMPE244 S16 Sound Buddy Reciever Speaker.JPG|500px]]
 +
|}
 +
 
 +
==== MP3 Decoder ====
 +
{|
 +
|-
 +
|[[File:CMPE244 S16 Sound Buddy PCB Top1.jpg|300px|left]]
 +
| When the PCB boards arrived, the components were carefully soldered on. The image on the left is the top of the of the board exposing the LEDs for debugging. The image on the right is the bottom of the board for reference.
 +
 
 +
| [[File:CMPE244 S16 Sound Buddy PCB Bottom1.jpg|300px|right]]
 +
|}
 +
 
 +
=== Software Implementation ===
 +
This section will explain the software implementation a little deeper but not too deep. You can check out the code in the References link to view the interworkings of the code. A Nordic wireless driver and MP3 decoder driver were adopted and updated to fit the current project code base. Minimal changes were made to accommodate the project. For the Nordic wireless driver, the Nordic mesh class was thrown out of the window removing any data checks for integrity. 
 +
 +
When the software was implemented, a variable was used to determine whether the code built was for the sender or the receiver.
 +
 
 +
<syntaxhighlight lang="cpp">
 +
#define NRF_SENDER 0          // 1 - Sender
 +
                              // 0 - Receiver
 +
</syntaxhighlight>
 +
 
 +
To distinguish between control commands and the music data, a data packet structure was created. The available commands are play, pause, stop, and end.
 +
 
 +
[[File:CMPE244 S16 Sound Buddy Data Packet.png|500px]]
 +
 
 +
 
 +
The following is the psuedo code on how the packet is built:
 +
<syntaxhighlight lang="cpp">
 +
void buildPacket(char * PACKET, header_cmd_t COMMAND, char * BUFFER, unsigned int DATASIZE){
 +
if DATASIZE > MAX_DATA_PACKET
 +
return;
 +
 
 +
PACKET[0] = (COMMAND << 5);
 +
PACKET[0] |= DATASIZE;
 +
 
 +
if(COMMAND == DATA)
 +
        memcpy(PACKET + PACKET_HEADER_SIZE, BUFFER, DATASIZE);
 +
}
 +
</syntaxhighlight>
 +
 
 +
==== Sender Board ====
 +
The  sender board depends primarily on two tasks, ReaderTask and SenderWirelessTask, to function properly after initialization.
 +
 
 +
The job of the ReaderTask is to retrieve the data from the SD card so the SenderWirelessTask can send the data out to the Nordic wireless output buffer.
 +
Below, are the steps the to achieve this.
 +
 
 +
Nordic Wireless Transmission
 +
 
 +
<syntaxhighlight lang="text">
 +
 
 +
  Step 1: Call the init function and set the device as a transmitter.
 +
  Step 2: Check if TX FIFO is full. If it's full, then wait, else continue to the next step.
 +
  Step 3: Send data packet to the TX FIFO. Data is sent out immediately from TX FIFO.
 +
 
 +
</syntaxhighlight>
 +
 
 +
An if-statement controls whether to send commands or the MP3 data at the user interface console.
 +
 
 +
<syntaxhighlight lang="cpp">
 +
if option == '1'
 +
      loop until end of DATA
 +
  READ_DATA_FROM_SD = (DATA);
 +
          xQueueSend(g_sender_queue, DATA, portMAX_DELAY );
 +
else if option == '2'
 +
buildPacket(PACKET, PLAY, NULL, 0);
 +
SenderWireless_service(PACKET);
 +
else if option == '3'
 +
buildPacket(PACKET, PAUSE, NULL, 0);
 +
SenderWireless_service(PACKET);
 +
else if option == '4'
 +
buildPacket(PACKET, STOP, NULL, 0);
 +
SenderWireless_service(PACKET);
 +
 
 +
 
 +
</syntaxhighlight>
 +
 
 +
 
 +
==== Receiver Board ====
 +
The receiver board requires the data packet to be parsed to pull the necessary information to process. Once the essential data is obtained, the data is sent through a queue to be saved into the SD card to be sent out to the MP3 decoder.
 +
 
 +
This code parses the packet to be processed in the recceiver tasks:
 +
<syntaxhighlight lang="cpp">
 +
void decodePacket(char* packet, header_cmd_t* cmd, char** dataPtr, unsigned int* dataSize){
 +
        *cmd = (header_cmd_t) ((packet[0] >> 5) & 0x07);
 +
        *dataSize = (packet[0] & 0x1F);
 +
        *dataPtr = packet + PACKET_HEADER_SIZE;
 +
}
 +
</syntaxhighlight>
 +
 
 +
The following are the steps the Nordic driver cycles through relative to the receive task.
 +
 
 +
Nordic Wireless Receive
 +
 
 +
<syntaxhighlight lang="text">
  
 +
  Step 1: Call the init function and set the device as a receiver.
 +
  Step 2: Check if data packet is available. If it's available, continue, else wait.
 +
  Step 3: Clear packet available flag.
 +
  Step 4: Read data packet from RX FIFO.
  
===PCB Layout===
+
</syntaxhighlight>
  
The PCB is a 2 layer board designed to plug into the SJSU ONE board connector directly.  
+
To handle the commands/data the following pseudo code is added to the receiver task:
 +
<syntaxhighlight lang="cpp">
 +
if cmd == DATA
 +
STORE_DATA(DATA)
 +
else if cmd == PLAY
 +
vTaskResume(mp3Task->getTaskHandle());
 +
else if cmd == PAUSE
 +
vTaskSuspend(mp3Task->getTaskHandle());
 +
else if cmd == STOP
 +
mp3Task->stop();
 +
vTaskSuspend(mp3Task->getTaskHandle());
 +
</syntaxhighlight>
 +
==== MP3 Decoder ====
 +
Once the STA013 MP3 decoder chip is initialized, sending data to the device becomes a breeze.
  
[[File:Decode-SJSU ONE Connection, Side View.jpg]]
+
A long list of configuration settings must be uploaded correctly to STA013. The following is the initialization code after uploading the settings is completed. The important configuration to note below is how the clocks are handled. Proper configuration of these rates are necessary to have STA013 functioning correctly.
  
'''The PCB layout'''
+
<syntaxhighlight lang="cpp">
 +
void sta013StartDecoder(void)
 +
{
 +
// Soft reset
 +
sta013WriteReg(STA_REG_SOFT_RESET, 0x01);
 +
sta013WriteReg(STA_REG_SOFT_RESET, 0x00);
  
[[File:PCB.png]]
+
// Mute
 +
sta013WriteReg(STA_REG_MUTE, 0x01);
  
=== Hardware Interface ===
+
// Configure DAC output for PCM1774 DAC:
In this section, you can describe how your hardware communicates, such as which BUSes used.  You can discuss your driver implementation here, such that the '''Software Design''' section is isolated to talk about high level workings rather than inner working of your project.
+
sta013WriteReg(STA_REG_PCMDIVIDER, 0x03); // changed to 256xFs 16-bit (used to be 0x01)
 +
sta013WriteReg(STA_REG_PCMCONF, 0x30); // changed to LRCKT I2S 16-bit mode (used to be 0x21)
  
There are four hardware communication interfaces in the Sound Buddy: SD card reading; Nordic wireless transmission; I2C bus communication between the Receiver board and the Decode board.
+
// Configure PLL for MP3 rates
 +
sta013WriteReg(STA_REG_PLLFRAC_441_H, 0x04);
 +
sta013WriteReg(STA_REG_PLLFRAC_441_L, 0x00);
 +
sta013WriteReg(STA_REG_PLLFRAC_H, 0x55);
 +
sta013WriteReg(STA_REG_PLLFRAC_L, 0x55);
 +
sta013WriteReg(STA_REG_MFSDF_441, 0x10);
 +
sta013WriteReg(STA_REG_MFSDF, 0x0F);
  
'''SD Card Reading'''
+
// Configure interface polarities, etc
The Sound Buddy reads the SD card using an SPI bus interface. The Sound Buddy will assume MP3 standard files are on the SD card. The rate at which the SD card is read is ???, this allows for reformatting of the data for transfer over the Nordic wireless communication link.
+
sta013WriteReg(STA_REG_RESERVED,      0x03);
 +
sta013WriteReg(STA_REG_PLLCTL_2, 0x0C);
 +
sta013WriteReg(STA_REG_PLLCTL_3, 0x00);
 +
sta013WriteReg(STA_REG_PLLCTL_1, 0xA1);
 +
sta013WriteReg(STA_REG_SCLK_POL, 0x00);
 +
sta013WriteReg(STA_REG_REQ_POL, 0x01);
 +
sta013WriteReg(STA_REG_DATA_REQ_ENABLE, 0x04);
 +
}
 +
</syntaxhighlight>
  
'''Nordic Wireless'''
+
The following is code that locks the SPI bus to send data out to the MP3 decoder. The lock is needed to prevent bus contention between the Nordic device and MP3 decoder
The maximum data transfer rate for the Nordic wireless is 250 Kbps. The Sound Buddy operates near this maximum.
 
  
'''I2C Bus Communication'''
+
<syntaxhighlight lang="cpp">
The I2C communication delivers, at minimum, 128 Kbps to the decode board. This means the Sound Buddy is capable of delivering radio quality sound.  Sound Buddy is capable of reading ITunes MP3 standard (256 Kbps) but play quality is limited to 128 Kbps.
 
  
=== Software Design ===
+
while(streamedBytes < bytesRead) {
Show your software design.  For example, if you are designing an MP3 Player, show the tasks that you are using, and what they are doing at a high level. Do not show the details of the code.  For example, do not show exact code, but you may show psuedocode and fragments of code.  Keep in mind that you are showing DESIGN of your software, not the inner workings of it.
+
    if(STA013_NEEDS_DATA()){
 +
spi1_lock;  
 +
SELECT_MP3_CS();
 +
ssp1_exchange_byte(data[streamedBytes++]);
 +
DESELECT_MP3_CS();
 +
spi1_unlock();
 +
}
  
[[File:file.jpg]]
+
</syntaxhighlight>
  
=== Implementation ===
+
<br>
This section includes implementation, but again, not the details, just the high level.  For example, you can list the steps it takes to communicate over a sensor, or the steps needed to write a page of memory onto SPI Flash.  You can include sub-sections for each of your component implementation.
 
  
 
== Testing & Technical Challenges ==
 
== Testing & Technical Challenges ==
 +
During the development of Sound Buddy, many problems came about. Some problems were resolved and others forced us to rethink the design. There was a lot of learning happening during the resolution of the problems.
 +
 +
This section aims to help you resolve design issues and give you hints on how to fix issues that we ran into.
 +
 +
<br>
 +
[[File:CMPE244 S16 Sound Buddy Debugging.jpg|center|700px]]
 +
<br>
 +
 +
=== Issue #1: Repurposing the existing Nordic driver code  ===
 +
In the SJOne project, a Nordic driver was already created. This was used for the implementation of a mesh network. Now, we were warned that this would lead to a lot of overhead and slowdown our code. We decided to make the driver lean and build it for the functions that we need. In doing so, things started to get complicated. Namely, the interrupt that was used in the existing driver was slowing our code down but at one point it was causing unexpected crashes.
 +
 +
=== Solution #1: Be simple, efficient ===
 +
We decided to try out a more simple way. There were functions in a lower level driver that allowed us to look at FIFO buffers. We went straight to the source instead of trying to get fancy. Even though using interrupts may have been considered best practice, for the purpose of having a functioning product at the end of the project deadline to demo, we simplified the sending and receiving of the data.
 +
 +
=== Issue #2: Buffer data transfer speed  ===
 +
This was a foreseen issue at the beginning of the project. How were we going to handle the buffer issue? Well, the buffer issue was only a problem when we were testing speeds. We didn't need the data to be sent very fast because we were limited buy the write speed of the SD card. We still wanted to see how fast we can get the speed to transfer.
 +
 +
=== Solution #2: Increase the data and buffer ===
 +
We didn't have time to implement a fully functional stream due to time constraints so we downloaded the file to the SD card on the receiver board instead. Essentially, the SD card was our buffer. We tested various solutions for a faster speed. These test results can be found in the Testing section below.
 +
 +
=== Issue #3: MP3 decoder circuit initialization  ===
 +
During the prototype of the MP3 decoder circuit, initializing the STA013 IC was the most difficult task. The chip required what looked like hundreds of registers to be initialized. This was too many to take into account for given the time crunch that we were in but we attempted to initialize anyway. We hit a brick wall and couldn't figure out why we get Ready signal but couldn't output any audible data.
 +
 +
=== Solution #3: Don't reinvent the wheel ===
 +
We resorted to using code that was dug up from another team's [http://www.socialledge.com/sjsu/index.php?title=S12:_Web-based_MP3_Player#Appendix project]. Using the STA013 driver in that project helped us initialize the STA013 chip properly.
 +
 +
=== Issue #4: MP3 decoder's unexpected behavior  ===
 +
We got the MP3 decoder to initialize but it still wasn't functioning properly.  We noticed a design flaw. Earlier, we had decided to hardwire the chip select on the STA013 IC thinking that it will always be enabled. This was giving us problems.
 +
 +
=== Solution #4: Exercise good practice with wiring HW ===
 +
The chip was working as expected as soon as we decided not to hardwire the chip enable on the board and instead use the STA013 driver's chip enable function to control it.
 +
 +
=== Issue #5: ICs were not what we expected  ===
 +
As we designed our PCB, we were still ordering our parts. Being novices with PCB design, we didn't double check the IC packaging. Wehen we recieved the PCB, we realized that the IC package for STA013 was bigger than we expected.
 +
 +
=== Solution #5: Make do with what you have ===
 +
In order to solve this, we could have reordered the PCB boards but that would take too long and cost too much. Instead, we decided to bend the legs in an utilize the teams soldering skills. We can be surgeons with these skill. JK.
 +
 +
<br>
 +
<br>
 +
==== The prototype board for the MP3 decoder circuit ====
 +
Before soldering the components on the PCB, we tested on a prototype board to make sure the design was functioning correctly. We found some connection issues and resolved it appropriately on the PCB when the components were soldered.
 +
<br>
 +
[[File:CMPE244 S16_SoundBuddy_ProtoType.png|600px]]
 +
<br>
 +
 +
=== Testing ===
 +
'''Nordic Test Cases'''
 +
* Sending a byte over nordic to all of the receiver devices
 +
* Sending text file over nordic to all of the receiver devices
 +
* Sending an MP3 file over nordic to a receiver device
 +
* Sending an MP3 file over nordic to all of the receiver devices
 +
* Performance test to increase data transfer speed of Nordic
 +
**The [http://elm-chan.org/fsw/ff/00index_e.html FATfs information site] was referenced to run similar [http://elm-chan.org/fsw/ff/img/rwtest1.png testbench] and understand how to increase data transfer rates.
 +
**The following is a list of test cases executed for performance testing:
 +
   
 +
<pre>
 +
  Format:
 +
        data, sizeof(data), wait, fileSize, priority
 +
 +
2 item, 1024 size, semaphore + delay(1), audio1 ~ 2mb
 +
time  bytes  kbps
 +
90144 2885632 256
 +
 +
2 item, 1024 size, poll, audio1 ~ 2mb
 +
time  bytes  kbps
 +
26948 2885632 856
 +
 +
10 item, 1024 size, poll, audio1 ~ 2mb
 +
time  bytes  kbps
 +
26947 2885632 856
 +
 +
10 item, 1024 size, poll, audio1 ~ 2mb, reader > sender
 +
time  bytes  kbps
 +
26917 2885632 857
 +
 +
2 item, 2048 size, poll, audio1 ~ 2mb, reader > sender
 +
time  bytes  kbps
 +
24978 2885632 924
  
'''Proto-Type'''
+
2 item, 4092 size, poll, audio1 ~ 2mb, reader > sender
 +
time  bytes  kbps
 +
22887 2883584 1007
  
[[File:S16_SoundBuddy_ProtoType.png]]
+
2 item, 4092 size, poll, audio1 ~ 2mb, reader = sender
 +
time  bytes  kbps
 +
21918 2883584 1052
  
Describe the challenges of your project. What advise would you give yourself or someone else if your project can be started from scratch again?
+
4 item, 4092 size, poll, audio1 ~ 2mb, reader = sender
Make a smooth transition to testing section and described what it took to test your project.
+
time  bytes bps
 +
21980 2883584 1049
  
Include sub-sections that list out a problem and solution, such as:
+
1 item, 4092 size, poll, audio1 ~ 2mb, reader
 +
time  bytes  kbps
 +
1 4096  32768
 +
</pre>
 +
<br>
 +
'''MP3 Decoder Tests Cases'''
 +
* Send a sample MP3 file from receiver's SD card
 +
* Send an full MP3 file from receiver's SD card
 +
<br>
 +
'''Integration Test Cases'''
 +
* Send and play an MP3 file to one reciever board
 +
* Broadcast to and play an MP3 file on all receiver boards
 +
<br>
  
=== My Issue #1 ===
+
All the test cases were executed. A handful failed at first execution but those that failed were resolved. The tests were run again until we agreed the function was behaving as expected and no major/minor defects were observed. At the end of the project cycle, all of the test cases listed above were run successfully.
Discuss the issue and resolution.
 
  
 
== Conclusion ==
 
== Conclusion ==
Conclude your project here. You can recap your testing and problems. You should address the "so what" part here to indicate what you ultimately learnt from this project. How has this project increased your knowledge?
+
Sound Buddy is only at its first stages of development. At the end of this project cycle, we have Sound Buddy demoing its ability to send data over Nordic and play music on one or multiple receiver devices.
 +
 
 +
[[File:CMPE244 S16 Sound Buddy PCB Side.jpg|600px|center]]
 +
 
 +
<br>
 +
 
 +
In relation to the FreeRTOS, we were able to exploit the function of queues to communicate between tasks. Our knowledge about the drivers in the SJOne project was also strengthened because we had to understand the drivers to utilize them with the peripherals. There was a lot of research that went into this project. The skill of reading datasheets was exercised extensively. This project was a practical use of the topics learnt from the Embedded Systems course at SJSU.
 +
 
 +
We were able to gain insight on how to work as a team to get things done. Even though we would have hoped to accomplish more with Sound Buddy such as a visually pleasing GUI, an actual stream of data from one board to the other, and professional product packaging, time became our biggest constraint. Working with such a diverse group of team members, we were able to learn from each other and adopt each others' skills at some points during the project.  
 +
 
 +
This project was a stressful yet enjoyable one to take part of.
  
 
=== Project Video ===
 
=== Project Video ===
Upload a video of your project and post the link here.
+
[https://youtu.be/D93sKmOlRlw Sound Buddy in ACTION!]
  
 
=== Project Source Code ===
 
=== Project Source Code ===
[https://sourceforge.net/projects/sjsu/files/CmpE_S2016/ Sourceforge Source Code Link]
+
[http://www.socialledge.com/sjsu/index.php?title=File:SP16_SOUND_BUDDY_Source.zip Sound Buddy's Guts (source code)]
 +
<br>
 +
<br>
 +
[[FILE:CMPE244 SP16_Sound_Buddy_Logo_2.jpg|200px]]
  
 
== References ==
 
== References ==
 
=== Acknowledgement ===
 
=== Acknowledgement ===
Any acknowledgement that you may wish to provide can be included here.
+
Preet Kang, who taught us what we needed to know to use the SJOne board and FreeRTOS for our project.
 +
<br>
 +
...And humor. For without it, we would not be able to enjoy each other's presence during the completion of this project.
 +
<br>
  
=== References Used ===
+
=== References ===
List any references used in project.
 
 
* Wiki Page Development
 
* Wiki Page Development
 
** <span class="plainlinks">[https://en.wikipedia.org/wiki/Help:List#Multi-column_bulleted_list Wiki Help List]</span>
 
** <span class="plainlinks">[https://en.wikipedia.org/wiki/Help:List#Multi-column_bulleted_list Wiki Help List]</span>
Line 339: Line 655:
  
 
* Project
 
* Project
 +
**[http://www.socialledge.com/sjsu/index.php?title=SJ_One_Board SJOne board]
 
** Nordic Wireless
 
** Nordic Wireless
 
***<span class="plainlinks">[http://www.socialledge.com/sjsu/index.php?title=Nordic_Low_Powered_Mesh_Network_stack Nordic Low Powered Mesh Network stack]</span>
 
***<span class="plainlinks">[http://www.socialledge.com/sjsu/index.php?title=Nordic_Low_Powered_Mesh_Network_stack Nordic Low Powered Mesh Network stack]</span>
 +
***[https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf Nordic wireless transceiver]
 +
***[http://elm-chan.org/fsw/ff/00index_e.html FATfs information site]
 +
***[http://elm-chan.org/fsw/ff/img/rwtest1.png Model FATfs testbench]
 
** MP3 Decoder
 
** MP3 Decoder
 
***<span class="plainlinks">[https://www.pjrc.com/mp3/sta013.html How To Use The STA013 MP3 Decoder Chip]</span>
 
***<span class="plainlinks">[https://www.pjrc.com/mp3/sta013.html How To Use The STA013 MP3 Decoder Chip]</span>
 
+
***[https://www.cirrus.com/en/pubs/proDatasheet/CS4334-5-8-9_F6.pdf CS4334 DAC]
=== Appendix ===
+
***[https://www.sparkfun.com/datasheets/Components/LM7805.pdf 7805 Voltage Regulator]
You can list the references you used.
+
***[https://learn.sparkfun.com/tutorials/how-to-install-and-setup-eagle EAGLE PCB]
 +
***[https://oshpark.com/ OSH Park]
 +
*** [http://www.socialledge.com/sjsu/index.php?title=S12:_Web-based_MP3_Player#Appendix MP3 Decoder Driver References]

Latest revision as of 03:38, 24 May 2016

Project Title

CMPE244 SP16 Sound Buddy Logo 1.jpg

Abstract

You turn up your music to rock out to but you forget your dancing shades in the other room so you run to the other room to look for it and by the time you find it your favorite part has already passed. Now, you have to start the song all over again.

What a bummer!

Sound Buddy is an affordable wireless speaker system designed to play your favorite music in any room you are walking into or every room. Load your favorite MP3 songs onto a micro SD card and plug it into Sound Buddy. Place the Sound Buddy speakers in any room, and you are ready. You can jam out to your favorite song and if you forget your favorite dancing shades again, Sound Buddy will switch the speaker in another room to blast your song. You will never miss your favorite part again!

Developed with amazing technologies such as the Nordic transceiver device, MP3 decoder, SJOne board, and the powerful FreeRTOS, Sound Buddy comes to life!

Walk through the design and development of the prototype for this exciting project.

Objectives

The implementation of Sound Buddy can be broken down into four main efforts.

Reading the MP3 File The MP3 file is read from a loaded mircoSD card to the SJSU-ONE board's flash memory.

Converting and Sending MP3 over Nordic Wireless The MP3 is wirelessly sent from the Sender-board's flash memory to the Receiver-boards' flash memory.

Receiving MP3 Files The Receiver-boards receive the MP3 file and prepare the MP3 file for transmission over an I2C communication bus to the MP3 decoder board.

Decoding MP3 to Audio The decoder board receives the file over the SPI communication bus and reformats the file to send raw data to the DAC where the speakers will be connected.

Team Members - Responsibilities

  • Brigitte De Leon - Tell everyone what to do
  • Catherine Gamboa - Be early to all the meetings
  • Hudo Assenco - Wake up
  • Yang Thao - Buy everything

The team members worked closely together every weekend of their hectic lives in the spring semester of 2016 to produce a beating heart for this project. Brigitte and Hudo worked on the Nordic wireless device code to get the data sent from one board to another in a streaming fashion. Catherine and Yang worked on the MP3 decoder circuit to be able to properly decode the MP3 file from the SJ-One board. Hudo and Catherine designed the PCB board that houses the MP3 decoder circuit. Yang made sure to supply the team with all of the material and then some. Brigitte brought the team together and kept the vision alive. Everyone put in time and effort to keep the Wiki document up-to-date through the duration of the project. Each sub team ran their own tests to assure that the subsystems were working as designed. The integration tests and debugging were tackled by all the members.

Schedule

Week# Date Task Actual
1 03.14
  • Finalize Schedule
  • Determine PCB board circuit
  • Order Parts
  • Update Wiki
  • Completed
  • 2 03.21
  • Design PCB schematic on Eagle
  • Review Nordic Wireless component on SJOne Board
  • Update Wiki
  • Completed
  • 3 03.28
  • Order PCB
  • Develop Nordic communication protocol
  • Write code to allow Nordic wireless communication between two boards
  • Update Wiki
  • PCBs received
  • Completed
  • 4 04.04
  • Build MP3 decoder prototype circuit and verify its functionality
  • Verify the Nordic wireless data transfer code works
  • Update Wiki
  • Completed
  • 5 04.11
  • Load small MP3 into SD card and send out to MP3 decoder to hear audio
  • Update Wiki
  • Completed.
  • Debugging MP3 Decoder prototype
  • Test Nordic wireless mesh commands
  • Solder ICs onto the PCBs
  • 6 04.18
  • Integrate the system (SD from Master -> Nordic Wireless -> Flash -> MP3 decoder circuit -> Speakers)
  • Update Wiki
  • Delayed progress...
  • Debugging MP3 Decoder prototype
  • Updating Nordic wireless class to remove delays
  • Send a file from one board to another with Nordic
  • Continue to solder ICs onto the PCBs
  • 7 04.25
  • Solder parts onto PCB
  • Integrate into test system
  • Update Wiki
  • Completed
  • Debugging MP3 Decoder prototype
  • Updating Nordic wireless class to send single byte
  • 8 05.02
  • Integration test
  • Update Wiki
  • Delayed progress...
  • Developed Nordic code to send a file to another board
  • Debugging MP3 Decoder prototype
  • 9 05.09
  • System test
  • Update Wiki
  • Delayed progress...
  • Optimizing Nordic code to send a file to another board
  • Debugging MP3 Decoder prototype
  • 10 05.16
  • Run final tests
  • Prepare for DEMO --> 05.24
  • Integration
  • PANIC!...JK
  • Completion of project's phase one
  • Parts List & Cost

    The parts tabulated below are those necessary to complete the project. It does not reflect the acutal parts used during testing also. During testing, extra devices were used to debug and replace damaged devices. Those dead components lay peacefully in our project graveyard.

    Item# Part Desciption Qty Cost per Item Cost
    1 STA013 MP3 Decoder Chip 2 $11.67 $23.34
    2 CS4334 DAC 2 $2.97 $5.94
    2 Audio Jack 3.5mm 2 $1.50 $4.50
    4 Crystal 14.7456MHz 2 $0.95 $1.90
    5 Printed Circuit Boards 2 $--.-- $32.05
    6 SparkFun SOIC to Dip Adapter 8-pin 1 $2.95 $2.95
    7 SparkFun SOIC to Dip Adapter 28-pin 1 $7.90 $7.90
    8 Breakaway headers 2 $1.50 $3.00
    9 Screw Terminals 3.5mm Pitch(2-Pin) 4 $0.95 $3.80
    10 Antennas 3 $4.20 $12.60
    11 Resistors 20 $0.19 $3.80
    12 Capacitors 120 $--.-- $20.11
    13 Inductors 2 $0.19 $0.38
    14 Voltage Regulators 2 $0.62 $1.24
    15 LEDs 8 $0.20 $1.60
    16 SJOne Board 3 $80.00 $240.00
    17 9V batteries 2 $-.-- $8.00
    Total Cost $-.-- $373.11

    Design & Implementation

    The following sections will walk you through the system design and dive into the implementation of Sound Buddy.

    After reading through the sections, you'll be able to understand what makes up Sound Buddy's beating heart.

    Hardware Design

    The hardware design was limited by the pins that the SJOne board provided. Luckily, this was not an issue for Sound Buddy. The protocols used were SPI/SSP and I2C so the number of pins were already availble for use of communication. A PCB was designed to house the MP3 decoder circuit. This PCB is mounted right on top of the SJOne board enclosing the unit as one functional device.

    System Design

    CMPE244 S16 Sound Buddy System Design.jpg
    Sound Buddy's core component is the SJOne board. For more information about the SJOne board click this link SJOne board or visit the main page of this Wiki.

    Its system is composed of a sender device and one or more receiver devices. An MP3 file will be stored on the micro SD card which will be inserted into the sender's SD slot. The sender device will read and send out the raw MP3 data over the Nordic wireless protocol. Each device uses the built-in Nordic wireless transceiver which allows for one-way communication from the sender to the receiver(s).

    Plugged onto each on the other receivers is the MP3 decoder circuit. The receiver device will be waiting for the MP3 data. Once it detects data has been sent over, it begins to process the data by sending it out to the MP3 decoder. The MP3 decoder translates the raw data and sends it out to the onboard DAC. The DAC converts the raw data into audible signals that get pushed out to the audio0 jack where the speakers play the music.

    Now, that was a mouthful. Let's dive deeper into each of the component design.



    Sender Board

    The sender board uses the SD card and the Nordic wireless transceiver onboard. Using the SPI protocol, the SD card will be enabled for I/O purposes. There is a total of four wires utilized namely the SCK, MOSI, MISO, and CS. These wires are connected internally and the data transfer and chip select are handled by the driver and application code.

    Similar to the SD card, the Nordic transceiver uses SPI protocol to send and receive data. This, too, is hooked up internally and the initialization and function are done through coding. The additional hardware part attached to the SJOne board is the 2.4GHz Duck Antenna RP-SMA to support the Nordic wireless data transfer. The Nordic data transfer can be sent on an on-air data rate of 250 kbps, 1Mbs, or 2Mbps depending on configuration. It has a maximum speed of 10Mbps on the SPI line and 3 separate 32 bytes TX and RX FIFO. On page 21 of the Nordic nrf24l01+ datasheet, the state diagram from communication can be found. Standby-II mode was used because it was determined to produce the fastest data transfer speed. If the TX FIFO detects a data packet uploaded, then the PLL starts and transmits immediately after PLL delay. To drive the Nordic device, the nrf24L01Plus class (included in the SJOne FreeRTOS project) was used to build a driver class. The driver simply checked if whether the TX FIFO is full and if it's not, data will be sent. It uses a polling method to achieve this.

    And, that is it for the sender device! Let's move on to the receiver device.

    CMPE244 S16 Sound Buddy Master Board.png

    Receiver Board

    CMPE244 S16 Sound Buddy Receiver Board.png
    The design of the receiver board is very similar to the sender board. Since its microcontroller is also the SJOne board, the onboard Nordic wireless transceiver and SD card slot were used for data transfer and storage. The raw data is sent over the Nordic wireless communication at about 200KBps even though it was able to send data at 1MBps. This is due to the write limitation that the available microSD cards imposed. The pins on the board for the SPI protocol are the same as those indicated in the sender board. A chip select pin was needed to enable the MP3 decoder. A GPIO pin from the SJOne board was configured for that purpose. The MP3 decoder board is connected on top of the SJOne board. The MP3 decoder shares the same SSP1 lines as the SD card. The software controls where the data transfer occurs. The MP3 decoder, also, utilizes the I2C protocol for initialization. The MP3 decoder circuit will be dissected later. Lastly, a speaker with an AUX port is attached to the MP3 decoder.

    MP3 Decoder

    This circuit is based on the tutorial that details how to use the STA013 chip. The MP3 decoder circuit uses an STA013 MP3 decoder chip to translate raw MP3 data to audible data. A detailed data sheet can be found at STA013 MP3 Decoder. We used the standard configuration suggested by the manufacturer which recommends that all of the voltage sources higher than 3.3V be brought down to 3.3V to safely operate the device. Since the voltage supply from the SJOne board is 3.3V, this was not an issue.

    For the data coming out of the MP3 decoder to produce music through speakers, the CS4334 DAC is used. This chip operates on a 5V supply so the SJOne board could not be used as a source. Instead, a 9V battery is used to supply the power. A 5V regulator circuit using a 7805 voltage regulator was built to step down the voltage level supply to prevent damage to the DAC device.

    An audio jack is tied to the output of the DAC device to send music out to speakers with an auxiliary port. The speakers are powered internally with a rechargeable baterry. Any off-the-shelf speaker can be transformed into a Sound Buddy receiver.


    CMPE244 S16 Sound Buddy MP3 Decoder Board.png

    Some assumptions are made about the usage of the STA013 device according to the tutorial. To summarize, for "normal" usage, its assumed that the STA013 will run off multimedia mode. The device will detect the MP3 data's bitrate and will send a signal that requesting for data. Data is fed to the STA013 up to 20Mbit/sec. The correct clock and data out to the DAC is also handled by the device. The STA013 will be driving the DAC and the output clock to synchronize with it. Since the tutorial uses a Cs4334 DAC chip in conjunction with a 14.7456 MHz crystal, those devices were used in the MP3 decoder as well. The DAC was chose due to it being inexpensive and its ability to output audio without noise.









    The following is an illustration of the circuit described in the STA013 tutorial. Each significant portion of the circuit is boxed and labeled. CMPE244 S16 Sound Buddy MP3 Decoder Schematic.png


    To package the MP3 decoder circuit nicely, a PCB was designed and printed to house the circuit. EAGLE PCB software was used to design the board layout. OSH Park was used to print the boards since the supply location was location locally in the Silicon Valley and the cost was affordable.

    LEDs were added in pins for enable and data signals to assist with debugging to assure that the MP3 was functioning as designed.

    CMPE244 S16 SoundBuddy PCB layers.png
    The illustration on the left is the layout the devices and interconnections on the board. It showcases both the top and bottom layers. The components were positioned with the thought of ease during the soldering of the devices and accessiblitity of the pins and ports.



    To the right are the images of the top and bottom of the expected layouts of the board. The PCB was designed to fit snuggly on top of the SJOne board. The pins on the right of the board align right on top the SJOne board's I/O pins to allow for accessibility.

    CMPE244 S16 SoundBuddy PCB Top Bottom.png

    Software Design

    The software design is separated by three different components that make up the Sound Buddy system. These components are the sender, receiver, and MP3 decoder. Each required a driver to be implemented to get the subsystems functioning properly.

    Sender Board

    The sender board was designed to initialize the necessary device drivers (SPI/SSP & Nordic wireless) and run FreeRTOS. The tasks created were used to read data from the SD card to the RAM and from the RAM, send the data to the Nordic wireless device. There were two tasks created, one to read from the SD card and another to write to SPI bus out the Nordic wireless device.

    CMPE244 S16 Sound Buddy SendTask.png


    Receiver Board

    The receiver board also initializes the necessary device drivers (SPI/SSP & Nordic wireless) and run FreeRTOS. It also depends primarily on two tasks. One task to wait for the RX FIFO to receive a data packet and the send task to handle the writing to the SD card. As soon as the MP3 file is completely loaded into the SD card, it waits for a command to be sent to control the MP3 decoder functionality.

    CMPE244 S16 Sound Buddy ReceiveTask.png

    MP3 Decoder

    The tutorial describes the configuration and use of the STA013 MP3 decoder chip. The basic configuration and data transmit are depicted in the flowchart below.

    CMPE244 S16 Sound Buddy MP3 Decoder Flow.png


    With an I2C address of 0x86, communicating to the MP3 decoder chip was simple after configuration. The SJOne board's code base includes an I2C driver that helped drive the communication. When you start feeding in valid MP3 data, the chip detects the MP3 sample rate and creates the correct clock for the DAC and starts pushing data into it. The STA013 will ignore non-MP3 data so it is safe to send the entire file without needing to strip out ID3 tags, etc. The STA013 expects the most significant bit first, which corresponds to the SPI standard.


    Hardware Implementation

    Sender & Receiver Board

    The following image is of the entire Sound Buddy system which includes the sender, receiver, and MP3 decoder board. The board in the middle is the sender board which is connected to the laptop to access the interface. The off-the-shelf speakers are connected to receiver boards.

    CMPE244 S16 Sound Buddy System ALL.png CMPE244 S16 Sound Buddy Reciever Speaker.JPG

    MP3 Decoder

    CMPE244 S16 Sound Buddy PCB Top1.jpg
    When the PCB boards arrived, the components were carefully soldered on. The image on the left is the top of the of the board exposing the LEDs for debugging. The image on the right is the bottom of the board for reference.
    CMPE244 S16 Sound Buddy PCB Bottom1.jpg

    Software Implementation

    This section will explain the software implementation a little deeper but not too deep. You can check out the code in the References link to view the interworkings of the code. A Nordic wireless driver and MP3 decoder driver were adopted and updated to fit the current project code base. Minimal changes were made to accommodate the project. For the Nordic wireless driver, the Nordic mesh class was thrown out of the window removing any data checks for integrity.

    When the software was implemented, a variable was used to determine whether the code built was for the sender or the receiver.

    #define NRF_SENDER 0          // 1 - Sender 
                                  // 0 - Receiver

    To distinguish between control commands and the music data, a data packet structure was created. The available commands are play, pause, stop, and end.

    CMPE244 S16 Sound Buddy Data Packet.png


    The following is the psuedo code on how the packet is built:

    void buildPacket(char * PACKET, header_cmd_t COMMAND, char * BUFFER, unsigned int DATASIZE){
    	if DATASIZE > MAX_DATA_PACKET
    		return;
    
    	PACKET[0] = (COMMAND << 5);
    	PACKET[0] |= DATASIZE;
    
    	if(COMMAND == DATA)
    	        memcpy(PACKET + PACKET_HEADER_SIZE, BUFFER, DATASIZE);
    }

    Sender Board

    The sender board depends primarily on two tasks, ReaderTask and SenderWirelessTask, to function properly after initialization.

    The job of the ReaderTask is to retrieve the data from the SD card so the SenderWirelessTask can send the data out to the Nordic wireless output buffer. Below, are the steps the to achieve this.

    Nordic Wireless Transmission

       Step 1: Call the init function and set the device as a transmitter.
       Step 2: Check if TX FIFO is full. If it's full, then wait, else continue to the next step.
       Step 3: Send data packet to the TX FIFO. Data is sent out immediately from TX FIFO.

    An if-statement controls whether to send commands or the MP3 data at the user interface console.

    if option == '1'
           loop until end of DATA
    	   READ_DATA_FROM_SD = (DATA);
               xQueueSend(g_sender_queue, DATA, portMAX_DELAY );
    else if option == '2'
    	buildPacket(PACKET, PLAY, NULL, 0);
    	SenderWireless_service(PACKET);
    else if option == '3'
    	buildPacket(PACKET, PAUSE, NULL, 0);
    	SenderWireless_service(PACKET);
    else if option == '4'
    	buildPacket(PACKET, STOP, NULL, 0);
    	SenderWireless_service(PACKET);


    Receiver Board

    The receiver board requires the data packet to be parsed to pull the necessary information to process. Once the essential data is obtained, the data is sent through a queue to be saved into the SD card to be sent out to the MP3 decoder.

    This code parses the packet to be processed in the recceiver tasks:

    void decodePacket(char* packet, header_cmd_t* cmd, char** dataPtr, unsigned int* dataSize){
            *cmd = (header_cmd_t) ((packet[0] >> 5) & 0x07);
            *dataSize = (packet[0] & 0x1F);
            *dataPtr = packet + PACKET_HEADER_SIZE;
    }

    The following are the steps the Nordic driver cycles through relative to the receive task.

    Nordic Wireless Receive

       Step 1: Call the init function and set the device as a receiver. 
       Step 2: Check if data packet is available. If it's available, continue, else wait.
       Step 3: Clear packet available flag.
       Step 4: Read data packet from RX FIFO.

    To handle the commands/data the following pseudo code is added to the receiver task:

    if cmd == DATA
    	STORE_DATA(DATA)
    else if cmd == PLAY
    	vTaskResume(mp3Task->getTaskHandle());
    else if cmd == PAUSE
    	vTaskSuspend(mp3Task->getTaskHandle());
    else if cmd == STOP
    	mp3Task->stop();
    	vTaskSuspend(mp3Task->getTaskHandle());

    MP3 Decoder

    Once the STA013 MP3 decoder chip is initialized, sending data to the device becomes a breeze.

    A long list of configuration settings must be uploaded correctly to STA013. The following is the initialization code after uploading the settings is completed. The important configuration to note below is how the clocks are handled. Proper configuration of these rates are necessary to have STA013 functioning correctly.

    void sta013StartDecoder(void)
    {
    	// Soft reset
    	sta013WriteReg(STA_REG_SOFT_RESET,		0x01);
    	sta013WriteReg(STA_REG_SOFT_RESET,		0x00);
    
    	// Mute
    	sta013WriteReg(STA_REG_MUTE,			0x01);
    
    	// Configure DAC output for PCM1774 DAC:
    	sta013WriteReg(STA_REG_PCMDIVIDER,		0x03); // changed to 256xFs 16-bit (used to be 0x01)
    	sta013WriteReg(STA_REG_PCMCONF,			0x30); // changed to LRCKT I2S 16-bit mode (used to be 0x21)
    
    	// Configure PLL for MP3 rates
    	sta013WriteReg(STA_REG_PLLFRAC_441_H,		0x04);
    	sta013WriteReg(STA_REG_PLLFRAC_441_L,		0x00);
    	sta013WriteReg(STA_REG_PLLFRAC_H,		0x55);
    	sta013WriteReg(STA_REG_PLLFRAC_L,		0x55);
    	sta013WriteReg(STA_REG_MFSDF_441,		0x10);
    	sta013WriteReg(STA_REG_MFSDF,			0x0F);
    
    	// Configure interface polarities, etc
    	sta013WriteReg(STA_REG_RESERVED,      		0x03);
    	sta013WriteReg(STA_REG_PLLCTL_2,		0x0C);
    	sta013WriteReg(STA_REG_PLLCTL_3,		0x00);
    	sta013WriteReg(STA_REG_PLLCTL_1,		0xA1);
    	sta013WriteReg(STA_REG_SCLK_POL,		0x00);
    	sta013WriteReg(STA_REG_REQ_POL,			0x01);
    	sta013WriteReg(STA_REG_DATA_REQ_ENABLE,		0x04);
    }

    The following is code that locks the SPI bus to send data out to the MP3 decoder. The lock is needed to prevent bus contention between the Nordic device and MP3 decoder

    while(streamedBytes < bytesRead) {
         if(STA013_NEEDS_DATA()){
    	spi1_lock;  
    	SELECT_MP3_CS();
    	ssp1_exchange_byte(data[streamedBytes++]);
    	DESELECT_MP3_CS();
    	spi1_unlock();
    }


    Testing & Technical Challenges

    During the development of Sound Buddy, many problems came about. Some problems were resolved and others forced us to rethink the design. There was a lot of learning happening during the resolution of the problems.

    This section aims to help you resolve design issues and give you hints on how to fix issues that we ran into.


    CMPE244 S16 Sound Buddy Debugging.jpg


    Issue #1: Repurposing the existing Nordic driver code

    In the SJOne project, a Nordic driver was already created. This was used for the implementation of a mesh network. Now, we were warned that this would lead to a lot of overhead and slowdown our code. We decided to make the driver lean and build it for the functions that we need. In doing so, things started to get complicated. Namely, the interrupt that was used in the existing driver was slowing our code down but at one point it was causing unexpected crashes.

    Solution #1: Be simple, efficient

    We decided to try out a more simple way. There were functions in a lower level driver that allowed us to look at FIFO buffers. We went straight to the source instead of trying to get fancy. Even though using interrupts may have been considered best practice, for the purpose of having a functioning product at the end of the project deadline to demo, we simplified the sending and receiving of the data.

    Issue #2: Buffer data transfer speed

    This was a foreseen issue at the beginning of the project. How were we going to handle the buffer issue? Well, the buffer issue was only a problem when we were testing speeds. We didn't need the data to be sent very fast because we were limited buy the write speed of the SD card. We still wanted to see how fast we can get the speed to transfer.

    Solution #2: Increase the data and buffer

    We didn't have time to implement a fully functional stream due to time constraints so we downloaded the file to the SD card on the receiver board instead. Essentially, the SD card was our buffer. We tested various solutions for a faster speed. These test results can be found in the Testing section below.

    Issue #3: MP3 decoder circuit initialization

    During the prototype of the MP3 decoder circuit, initializing the STA013 IC was the most difficult task. The chip required what looked like hundreds of registers to be initialized. This was too many to take into account for given the time crunch that we were in but we attempted to initialize anyway. We hit a brick wall and couldn't figure out why we get Ready signal but couldn't output any audible data.

    Solution #3: Don't reinvent the wheel

    We resorted to using code that was dug up from another team's project. Using the STA013 driver in that project helped us initialize the STA013 chip properly.

    Issue #4: MP3 decoder's unexpected behavior

    We got the MP3 decoder to initialize but it still wasn't functioning properly. We noticed a design flaw. Earlier, we had decided to hardwire the chip select on the STA013 IC thinking that it will always be enabled. This was giving us problems.

    Solution #4: Exercise good practice with wiring HW

    The chip was working as expected as soon as we decided not to hardwire the chip enable on the board and instead use the STA013 driver's chip enable function to control it.

    Issue #5: ICs were not what we expected

    As we designed our PCB, we were still ordering our parts. Being novices with PCB design, we didn't double check the IC packaging. Wehen we recieved the PCB, we realized that the IC package for STA013 was bigger than we expected.

    Solution #5: Make do with what you have

    In order to solve this, we could have reordered the PCB boards but that would take too long and cost too much. Instead, we decided to bend the legs in an utilize the teams soldering skills. We can be surgeons with these skill. JK.



    The prototype board for the MP3 decoder circuit

    Before soldering the components on the PCB, we tested on a prototype board to make sure the design was functioning correctly. We found some connection issues and resolved it appropriately on the PCB when the components were soldered.
    CMPE244 S16 SoundBuddy ProtoType.png

    Testing

    Nordic Test Cases

    • Sending a byte over nordic to all of the receiver devices
    • Sending text file over nordic to all of the receiver devices
    • Sending an MP3 file over nordic to a receiver device
    • Sending an MP3 file over nordic to all of the receiver devices
    • Performance test to increase data transfer speed of Nordic
      • The FATfs information site was referenced to run similar testbench and understand how to increase data transfer rates.
      • The following is a list of test cases executed for performance testing:
      	Format: 
            data, sizeof(data), wait, fileSize, priority
    	
    	2 item, 1024 size, semaphore + delay(1), audio1 ~ 2mb
    	time   bytes  kbps
    	90144 2885632 256
    
    	2 item, 1024 size, poll, audio1 ~ 2mb
    	time   bytes  kbps
    	26948 2885632 856
    
    	10 item, 1024 size, poll, audio1 ~ 2mb
    	time   bytes  kbps
    	26947 2885632 856
    
    	10 item, 1024 size, poll, audio1 ~ 2mb, reader > sender
    	time   bytes  kbps
    	26917 2885632 857
    
    	2 item, 2048 size, poll, audio1 ~ 2mb, reader > sender
    	time   bytes  kbps
    	24978 2885632 924
    
    	2 item, 4092 size, poll, audio1 ~ 2mb, reader > sender
    	time   bytes  kbps
    	22887 2883584 1007
    
    	2 item, 4092 size, poll, audio1 ~ 2mb, reader = sender
    	time   bytes  kbps
    	21918 2883584 1052
    
    	4 item, 4092 size, poll, audio1 ~ 2mb, reader = sender
    	time   bytes  bps
    	21980 2883584 1049
    
    	1 item, 4092 size, poll, audio1 ~ 2mb, reader
    	time   bytes  kbps
    	1 	4096  32768
    


    MP3 Decoder Tests Cases

    • Send a sample MP3 file from receiver's SD card
    • Send an full MP3 file from receiver's SD card


    Integration Test Cases

    • Send and play an MP3 file to one reciever board
    • Broadcast to and play an MP3 file on all receiver boards


    All the test cases were executed. A handful failed at first execution but those that failed were resolved. The tests were run again until we agreed the function was behaving as expected and no major/minor defects were observed. At the end of the project cycle, all of the test cases listed above were run successfully.

    Conclusion

    Sound Buddy is only at its first stages of development. At the end of this project cycle, we have Sound Buddy demoing its ability to send data over Nordic and play music on one or multiple receiver devices.

    CMPE244 S16 Sound Buddy PCB Side.jpg


    In relation to the FreeRTOS, we were able to exploit the function of queues to communicate between tasks. Our knowledge about the drivers in the SJOne project was also strengthened because we had to understand the drivers to utilize them with the peripherals. There was a lot of research that went into this project. The skill of reading datasheets was exercised extensively. This project was a practical use of the topics learnt from the Embedded Systems course at SJSU.

    We were able to gain insight on how to work as a team to get things done. Even though we would have hoped to accomplish more with Sound Buddy such as a visually pleasing GUI, an actual stream of data from one board to the other, and professional product packaging, time became our biggest constraint. Working with such a diverse group of team members, we were able to learn from each other and adopt each others' skills at some points during the project.

    This project was a stressful yet enjoyable one to take part of.

    Project Video

    Sound Buddy in ACTION!

    Project Source Code

    Sound Buddy's Guts (source code)

    CMPE244 SP16 Sound Buddy Logo 2.jpg

    References

    Acknowledgement

    Preet Kang, who taught us what we needed to know to use the SJOne board and FreeRTOS for our project.
    ...And humor. For without it, we would not be able to enjoy each other's presence during the completion of this project.

    References