Seven Segment Board with NuttX

In this second installment, in the Seven Segment series we are going to see how to interface the Seven Segment Display Board with NuttX. If you haven’t, you might want to read the Seven Segment board fundamentals described in the blog article Seven Segment Board, Getting Started, before reading this article.

Hardware

  • Seven Segment Board

  • ZKit-ARM-1769 Board

Hardware Connections

We don’t have the dedicated 14 pin DIO header in the ZKit-ARM-1769, required for the Seven Segment Board. Hence, we are going to make some hardware setup to connect the Seven Segment board.

We are going to use GPIO pins in I2C and SPI header in order to get the twelve pins connection, 8 pins for data, 3 pins for address and 1 Pin for selection`.

Following table shows the pin connection for seven segment board with ZKit-ARM-1769

Table 1. Pin Connection Using I2C and SPI as a DIO header
S.No Description on controller side Header name Pin no in Seven Segment board Signal name in seven segment

1

VCC

SPI

1

VCC

2

P0.7/SCK1

SPI

2

DOUT0

3

P0.8/MISO1

SPI

3

DOUT1

4

P0.9/MOSI1

SPI

4

DOUT2

5

P0.6/SSEL1

SPI

5

DOUT3

6

P0.4

SPI

6

DOUT4

7

P0.5

SPI

7

DOUT5

8

P4.28

SPI

8

DOUT6

9

P4.29

SPI

9

DOUT7

10

P2.1/RXD1

I2C

10

DIN0

11

P2.0/TXD1

I2C

11

DIN1

12

P0.28/SCL0

I2C

12

DIN2

13

P0.27/SDA0

I2C

13

DIN3

14

GND

I2C

14

GND

Software

As per the algorithm given in the "Seven Segment Board, Getting Started" article, we are going to build the software to display a string of digits on the Seven Segment Display Board. To acheive this we are going to implement following functions:

  • sseg_init()

  • sseg_set_multi_pins()

  • sseg_digits_off()

  • sseg_on_digit()

  • sseg_putc()

  • sseg_puts()

Initialization

In sseg_init() the GPIO pins for data and address lines are initialized.

Setting Multiple pins

It is required to set multiple GPIO pins in one go, when setting the digit selection and when driving the segments. The function sseg_set_multi_pins() allows us to do exactly this.

Digits off

In sseg_digits_off() all seven segment digits are turned off.

Turning on a Segment with a digit

In sseg_on_digit() a partiticular seven segment digit is selected, by driving the digit selection GPIO pins.

Displaying a digit

In sseg_putc(), a particular seven segment digit is selected and the segment GPIO pins are driven to shown a number between 0 and 9.

Displaying multiple digits

In sseg_puts(), each character from the specified string is displayed on the corresponding seven segment digit.

After the digit is displayed, a delay of 2ms is introduced so that the digit is visible for atleast 2ms, before the next digit is displayed.

#include <nuttx/config.h>
#include <chip/lpc17_gpio.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>

/* GPIO configuration */
#define A (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN7)
#define B (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN8)
#define C (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN9)
#define D (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN6)
#define E (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN4)
#define F (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN5)
#define G (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT4 | GPIO_PIN28)
#define H (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT4 | GPIO_PIN29)
#define A0 (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT2 | GPIO_PIN1)
#define A1 (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT2 | GPIO_PIN0)
#define A2 (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN28)
#define SEL (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN27)

#define MAX_SEG 8
#define MAX_DIGIT 8
#define MAX_ADD 4

/* Segments */
int segments[] = {A, B, C, D, E, F, G, H};

/* Address and Selection line for 8 digits */
int add_pins[] = {A0, A1, A2, SEL};

uint32_t encode_digit[] = {
        0x3f,  /* 0 */
        0x06,  /* 1 */
        0x5B,  /* 2 */
        0x4F,  /* 3 */
        0x66,  /* 4 */
        0x6D,  /* 5 */
        0x7D,  /* 6 */
        0x07,  /* 7 */
        0x7F,  /* 8 */
        0x67,  /* 9 */
};

/*
 * Initiailze IO pins for seven sgment display.
 */
void sseg_init(void)
{
        int i;
        for (i = 0; i < MAX_SEG; i++) {
                lpc17_configgpio(segments[i]);
                lpc17_gpiowrite(segments[i], false);
        }

        for (i = 0; i < MAX_ADD; i++) {
                lpc17_configgpio(add_pins[i]);
                lpc17_gpiowrite(add_pins[i], false);
        }

}

/*
 * Turn off all digits.
 */
void sseg_digits_off(void)
{
        int i;
        for (i = 0; i < MAX_DIGIT; i++)
                lpc17_gpiowrite(segments[i], false);
}

/*
 * Turn on the pins specified by no of bits.
 */
void sseg_set_multi_pins(int pin[], int nobits, uint8_t data)
{
        int i;
        for (i = 0; i < nobits; i++)
                lpc17_gpiowrite(pin[i], data & 1 << i);
}

/*
 * Turn on a digit for example if digit is 8 it will turn on 8 the digit
 */
void sseg_on_digit(uint32_t digit)
{
        uint8_t i;
        sseg_set_multi_pins(add_pins, 3, digit);
}

/*
 * Display the character encoded to digits.
 */
void sseg_putc(signed char ch, uint32_t digit)
{
        sseg_digits_off();
        sseg_on_digit(digit);
        /* SEL pin should be low in order to activate the board */
        lpc17_gpiowrite(SEL, false);
        sseg_set_multi_pins(segments, MAX_SEG, encode_digit[ch]);
        up_mdelay(2);
}

/*
 * The char given as a string is displayed on the display.
 */
void sseg_puts(char *str)
{
        int digit = MAX_DIGIT;
        while (*str) {
                sseg_putc(*str - '0', --digit); /* char to int */
                str++;
                if (digit < 1)
                        digit = MAX_DIGIT;

        }
}

int app_main(int argc, char *argv[])
{
        sseg_init();

        while (1)
                sseg_puts("12345678");

}

Credits

The Seven Segment Digit image is based on this Seven Segment image from Wikimedia Commons.