Purpose of Drivers

Why does the code base use “drivers”? What are these things?

Under the Hood

At a highish level, what does a driver do under the hood? How does it interface with the FPGA?


Looking at examples is helpful – here are some common drivers that the user will access frequently.

Reading Analog Values from ADC

There are 16 ADC channels which provide analog input into the AMDC. Each channel supports +/- 10V inputs. To read the analog voltage on these inputs, the drv/analog.c driver is used. The user code simply calls a driver function which returns the voltage value. You might expect it to work like the following: Imagine I have 5V applied to the ADC on channel 1. Then,

float voltage = analog_read(channel_1); // voltage should now equal 5.0

You’ll be happy to find that the actual driver code functions almost the same as this. However, if the user asks for a channel which is not valid (i.e., channel_100), the driver should indicate this is an error. To do this, the driver function return value is the error indicator. To get the analog voltage value, the user supplies the driver function with a memory address where it should put the analog voltage value. For the same example as above:

// Create variables to use
int err;
float voltage;

// Call driver function
err = analog_read(channel_1, &voltage);

// Now:
// - 'err' will be the return status of the driver function
// - 'voltage' should equal 5.0

We are almost to the final code which you will use in your applications. However, you will find that the function analog_read(...) does not exist. Instead, there are two functions: analog_geti(...) and analog_getf(...). The first gets the ADC voltage value as an int while the second retreives it as a float. The analog_geti(...) variant is lower-level; it outputs the actual value returned by the ADC. The analog_getf(...) variant should be used most of the time; it returns the actual voltage on the ADC input.

Also, you will find that channel_1 does not exist. Instead, you should use the enumeration provided in drv/analog.h. The mapping between enumeration and ADC channel is nearly 1:1 – use ANALOG_IN1 for channel 1, ANALOG_IN2 for channel 2, etc.

So, the final version of the code you will use is as follows:

// Create variables to use
int err;
float voltage;

// Call driver function
err = analog_getf(ANALOG_IN1, &voltage);

// Now, you have your output

Writing PWM Duty Ratios

Similar to steps for reading voltages, but with drv/pwm.c driver.

Reading Encoder Values

Similar to steps for reading voltages, but with drv/encoder.c driver.