The software used in this project consists in: two Arduino firmwares responsible for the modulation and transmission of data with its counterpart of demodulation plus display of said data and a graphical user interface (GUI) focused on the input of user data via PC.

Arduino Firmware: Transmission

The goal of this firmware is to manipulate the information inputted by the user via GUI so it can be properly transmitted. In this project we chose to implement the concept which is behind a common numerical modulation: Frequency Shift Keying (FSK). The data is transferred from the PC to the Arduino board via serial communication. Each datum is encoded as a string, so we need to convert it into a numeric type variable, which can be easily done with Arduino's library functions. Once the datum is a numeric variable, ie BYTE (8 bits) or FLOAT (32 bits). It is possible to access every single bit of the BYTE variable again by using a library function. Instead for a FLOAT variable it is a bit more difficult since we had to declare a STRUCT in order to extract the single bits of the digital number. Once the extraction of bits is done, the focus shifts on how to transmit the values. We based our transmission method on the FSK concepts: in the modulation, the '0' value is assigned to a specific frequency while the '1' value is assigned on a different frequency. So in our project we decided to assign a frequency of 250 Hz (4 ms) to '0' value and 500 Hz (2 ms) to '1' value while our carrier has a frequency of 125 Hz (8ms). The signal on the output pin is a square wave and these frequency ensure that there's no flicker on the emitted light. In order to properly synchronize the receving and transmitting devices we employed a header consisting in a sequence of 56 fixed bits which are '0' and '1' alternating. This way it is possible to know how many signal edges have to be read by the receiver to know that there's a transmission of data incoming and the edges are not due to noise or interference.
The version of the firmware used in the transmitting Arduino can be found here

Arduino Firmware: Reception

This part is a bit trickier because we have to rely on Arduino built-in circuitry for the reading of the signal which will be then properly demodulated to reconstruct the original data. Knowing how the transmission works, we implemented an interrupt routine to count the rising edge of the signal on the input pin. The interrupt signal is set on the rising edge so everytime the voltage surpasses a threshold specified in the Arduino datasheet, a counter is increased and then used to know how many edges we received. This is why the signal integrity is crucial: if a noise is applied to it there's the possibility that the reading will be corrupted if the circuitry inside Arduino misinterprets the transition from low to high (ie the signal isn't monotonic in a neighbourhood of the threshold). And that is also reason why we used the hex inverters in the 74HC04 chip: the inverters provide a shaper shape of the signal granting a faster and more defined transition removing the influence of the noise. Once the signal is properly conditioned to be read, the firmware is in charge of counting how many edges are received in a fixed amount of time so that it is possible to discern wheter a '0' or a '1' was sent. More specifically, given our carrier is at 125 Hz we know that in a period we receive 4 rising edge if a '1' was transmitted (500/125 = 4) while on the other hand if we receive 2 edges we know that a '0' was transmitted. Thanks to the header sent by the transmitter it is possible to properly synchronize the receiver to the data and so we manage to reconstruct what was sent, specifically the ID of the tag and the price.

Error checking and correction
During our testing we found that the majority of errors was due not to the misinterpretation of the edges representing the single bit, rather to the total length of the packet read by the receiver. Since we know by design that the all packets have a fixed length and more specifically all the parts of the packet have a fixed length, as a way of error-checking we only measured the length of the received data of each part of the packet. If a single one of the three is found not corresponding to what we expect, the whole packet is discarded and the receiver is set in listen mode again, waiting for another transmission. In combination with the periodic refresh we supposed in the transmission side this acts as a way of error checking and error correction.
The version of the source code implemented in the receiving Arduino can be found here

GUI Software

We developed a basic graphic user interface with the help of Microsoft Visual Studio in order to handle the communication between the user PC and the Arduino chip using the serial port communication. In this interface it's possible to specify the device ID we want to update and also the price we want to set. Since the program relies on the microsoft framework for the serial communication we use a USB port that acts like a serial port and from a selection bar it is necessary to specify to which port the device is connected. It's important to mention that if you connect to the device via this interface there's no possibility to employ the serial monitor built in the Arduino IDE, which we use to verify if the receiver interpreted correctly the received signal.
The source code for the GUI app can be found here