# AN02036: Making an LED glow using Pulse Density Modulation£££doc/rst/an02036.html#an02036-making-an-led-glow-using-pulse-density-modulation

This application note describes how to control the brighness of an LED by implementing a Pulse Density Modulator, or PDM. This note focuses on the XCORE aspects (I/O and timing) and we give a brief explanation on how a PDM is implement it. We describe different, equally valid, methods to implement this on an XCORE. The method one deploys will depend on how it is integrated in a system.

## AN02036: Making an LED glow using Pulse Density Modulation$$$Modulation£££doc/rst/an02036.html#modulation

In the code below we use Pulse Density Modulation to glow the LED. In Pulse Density Modulation you, on a clock beat, drive either a high signal or a low signal. You do this so that the average signal over many clock beats is the desired output.

The code we use implements a very basic Pulse Density Modulator that is suitable for glowing an LED. Let us assume that the level that we want the LED to glow at is a real number in the range [0..1] inclusive, where 0 means completely off, and 1 means completely on.

The trick is to maintain a fraction of time that we have yet to be on for. This is an accumulated error. On every clock-beat we add the level that we want to be at to the accumulated error, and if the result is 1.0 or more we switch the LED on for that next beat. Otherwise we switch the LED off for that beat:

- Add level to the accumulated error

- If the accumulated error is 1.0 or more then the LED must be ON for a clock-beat, and subtract we record this by subtracting 1.0 from the accumulated error

- Else LED is OFF for one clock-beat

Assuming that we want to drive 0.65 as a value, we go through the following sequence:

> Error | Level | Error+Level | Output | New Error
> --- | --- | --- | --- | ---
> 0.0 | 0.65 | 0.65 | OFF | 0.65
> 0.65 | 0.65 | 1.30 | ON | 0.30
> 0.30 | 0.65 | 0.95 | OFF | 0.95
> 0.95 | 0.65 | 1.60 | ON | 0.60
> 0.60 | 0.65 | 1.25 | ON | 0.25
> 0.25 | 0.65 | 0.90 | OFF | 0.90
> 0.90 | 0.65 | 1.55 | ON | 0.55
> 0.55 | 0.65 | 1.20 | ON | 0.20
> 0.20 | 0.65 | 0.85 | OFF | 0.85

..and so on. You can see that the LED seems to be mostly going through a sequence ON ON OFF, (2/3, or 0.667); with the occasional extra OFF it will be on for 13 out of every 20 clock beats

In order to implement this, we have not used real numbers but instead integers in the range [0..100] inclusive, where 0 is OFF, and 100 is OFF. This means that the level can be seen as a percentage:

    #include <xcore/port.h>
    #include <xcore/clock.h>
    #include <platform.h>

    port_t led = PORT_LEDS;

    void glow_fixed_simple(int percentage) {
        int accumulator = 0;
        for(int i = 0; i < 10000000; i++) {
            int on;
            accumulator += percentage;
            if (accumulator >= 100) {
                on = 1;
                accumulator -= 100;
            } else {
                on = 0;
            }
            port_out(led, on);
        }
    }

There is one line in the code above which is not standard `C`, which is the function call `port_out(led, on)`. This call outputs (drives) the value found in the variable `on` onto the port found in `led`. In this case, `led` is a global variable that refers to the port on which the LEDs are connected. If `on` is the value `1`, then a high VDDIO signal will be driven, if `on` is the value `0`, then VSS (0 V) will be driven.

More information on XCORE ports can be found in AN03000: XCORE Input and Output and AN03007: XCORE Ports.

## AN02036: Making an LED glow using Pulse Density Modulation$$$Glow an LED Using a Timer£££doc/rst/an02036.html#glow-an-led-using-a-timer

The above modulator switches the LED on and off, but the period of ON and OFF depends on the length of time executed in each of the branches of the IF statement.

We can make this precise by using a timer. We increment the timer at some fixed interval, and we wait for each next interval before we drive the port on or off.

    #include <xcore/hwtimer.h>
    #include <xcore/port.h>

    void glow_fixed_timer(int percentage) {
        hwtimer_t tmr = hwtimer_alloc();
        int accumulator = 0;
        int next_time = hwtimer_get_time(tmr);
        for(int i = 0; i < 5000; i++) {               // five seconds
            int on;
            accumulator += percentage;
            if (accumulator >= 100) {
                on = 1;
                accumulator -= 100;
            } else {
                on = 0;
            }
            next_time += 100000;                      // 1 ms
            hwtimer_set_trigger_time(tmr, next_time);
            (void) hwtimer_get_time(tmr);
            port_out(led, on);
        }
        hwtimer_free(tmr);
    }

There are four calls involved in the timer. The first call `hwtimer_alloc()` allocates a hardware timer from the pool of timers. There is an associated `hwtimer_free(tmr)` at the end of the function to put the timer back in the pool.

Timers run at 100 MHz (100,000,000 Hz). The function `hwtimer_get_time(tmr)` gets the current value of the timer. We can add 100,000 to this timer value (100,000/100 MHz = 1 ms) and then set this time up as the trigger. Now that the trigger is set, getting the time will wait until the trigger time has been reached, and we can ignore the result as we know that it is one millisecond later, and we adjust the LED value. As we only ever add one millisecond at a time to the timer we never miss any time; this code will, on average, run at exactly 1 kHz, with a few nanoseconds of jitter on each edge.

Timers are documented in lib_xcore documentation.

## AN02036: Making an LED glow using Pulse Density Modulation$$$Using a Port Clock£££doc/rst/an02036.html#using-a-port-clock

The final way to glow an LED we discuss is to use the port-clock. Each port has an associated clock signal that is used to operate the port. The port can only change on a positive clock edge, and by setting the port to be clocked at a known future edge we can achieve the same effect as using the timer. We keep track of the number of the clock edge in a variable `clock_edge_number`:

    #include <xcore/port.h>
    #include <stdint.h>

    void glow_clocked(int percentage) {
        static int accumulator = 0;
        static uint16_t clock_edge_number = 0;
        accumulator += percentage;
        clock_edge_number += 50000;
        port_set_trigger_time(led, clock_edge_number);
        if (accumulator >= 100) {
            accumulator -= 100;
            port_out(led, 1);
        } else {
            port_out(led, 0);
        }
    }

In this code we have removed the for-loop, and instead `glow_clocked()` will have to be called repeatedly. The variables `accumulator` and `clock_edge_number` have been declared `static` so that their value is maintained across function calls. We set the clock-edge-number at which we wish to output using `port_set_trigger_time()`, and we add 50,000 to the clock edge number on every iteration. As a port is clocked by default from a 100 MHz clock, this will result in a PDM that runs at exactly 2 kHz, with negligible jitter on the edges.

Port edges are only counted in a 16-bit number (the counter is therefore declared as a `uint16_t`), so 65,535 is the highest step we can make. More information on clocked ports can be found in AN03001: XCORE Clocked Input and Output. In particular, that document tells you how to obtain the current clock-edge, or how to use clocks that are not 100 MHz.

## AN02036: Making an LED glow using Pulse Density Modulation$$$Variable Glow£££doc/rst/an02036.html#variable-glow

The previous two examples had a fixed level (eg, 65), in this example we pulse the value gently at 1 Hz using a sine waveform. For this we call the function `sinf` in order to calculate a raised sine wave. We use the API we defined earlier and use a clocked port from the previous section for creating a glow:

    #include <math.h>

    void pulse() {
        for(int i = 0; i < 10000; i++) {               // five seconds
            glow_clocked(50 + 50 * sinf(i / 2000.0 * 2 * 3.14));
        }
    }

## AN02036: Making an LED glow using Pulse Density Modulation$$$Summary£££doc/rst/an02036.html#summary

This application note gives a brief overview of some ways to control the brightness of an LED to illustrate key XCORE port operations: how to create a modulator, how to use a timer, how to use a port-clock, and how to make sure the LED looks pretty.