circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

October 2005, Issue 183

The Silicon Wallet
CY8C27443-Based Data Manager


STYLE VALUE

The application code, which is written in C, takes 32% of the CY8C27443’s flash memory, leaving more than two-thirds of the nonvolatile memory for storing user data. As I developed the code, I placed each logic block in a separate module, banning the use of global variables whenever possible. This is a discipline I learned the hard way, working on large projects with other programmers, but it’s also useful in small designs because it enables you to make changes easily. The price to pay for flexibility is that the code is dispersed in many files. But this practice pays for itself when it’s applied correctly. Touching one module doesn’t affect the others. Therefore, you can invent a different keyboard layout, try an error correction code other than the Hamming, or experiment with a new offset-level control strategy, concentrating the changes on one module at a time.

The receive() function demonstrates how modularization is implemented. The function in Listing 1 attempts to receive a code word from the light detector; it keeps trying until a new code word is detected or the quadrature encoder button is released. It does its job one bit at a time, calling the receive_bit() function, a lower-level routine that can return 0, 1, or BIT_INVALID. The last value indicates an error or a timeout condition, in which case the receiver discards all the previously received bits and restarts.

The receive() function reduces the problem of receiving a code word to the problem of receiving a single bit. This new problem is handled by the receive_bit() function (see Listing 2). The protocol encodes bits as the sequence starting with a logic 1 (for 45 to 90 ms) followed by a logic 0 (45 ms). Based on the duration of the previous sequence (with due tolerances), the function determines if the previously received bit is a 1 (shorter) or a 0 (longer). Timeouts are provided during reception to abort the operation if no valid data arrives after a fixed amount of time.

At this stage, the problem is reduced to detecting input logic levels with a couple of functions: is_one() and is_zero(). This is done in another module that reads the A/D converter, adds hysteresis, fills inter-frame gaps in CRT monitors, and so on. Refer to the light_sensor.c file posted on the Circuit Cellar FTP site.

It’s important to note that as long as you provide the same couple of functions, the receiver code will continue to work untouched even if the logic levels are determined in a different way. The mechanism is flexible. For example, you may want to experiment with a two-tone sound as a data source in place of light, or you can get the data as a logic level from an external circuit connected directly to an I/O pin. In both cases, all you have to do is replace is_one() and is_zero() with an alterative implementation.