SLAAEC7 September   2024

 

  1.   1
  2. Description
  3. Required Peripherals
  4. Compatible Devices
  5. Design Steps
  6. Design Considerations
  7. Software Flow Chart
  8. Application Code
  9. Hardware Design
  10. Results
  11. 10Additional Resources
  12. 11E2E
  13. 12Trademarks

Application Code

This application makes use of the TI System Configuration tool (SysConfig) graphical interface to generate the configuration code for the device peripherals. Using a graphical interface to configure the device peripherals streamlines the application prototyping process.

There are a few key variables that this example uses: the number of rows, the column mask value, the display period duration, and a counter to track the number of interrupts. The number of rows is a defined value that is used to build the memory table array. The column mask is equivalent to the bitwise OR of the GPIO values of all of the column pins used. The column mask is used with the memory table to determine which column pins need to be on or off per row at a given time. The display period variable is multiplied by the duration of time per timer interrupt to determine the amount of time that a single memory table write is used. For this example, the display period value is defined as 100 which equates to a display period time of half a second. The counter, or gLedState, is used to track the number of interrupts in relation to the display period value. This makes sure that the memory table is written to every display period.

#define NUMBER_OF_ROWS 3
#define COL_MASK 0x38
#define LED_DISPLAY_PERIOD 100 /* timer period = 5 ms, so display period = 500 ms */
volatile uint32_t gLedState = 0;
void LED_updateTable(uint8_t rowNumber, uint8_t LEDs);

The next snippet of code shows the enumeration table as well as the timer Interrupt Request (IRQ). The enumeration table defines the row states that the rowState switch cycles through in the timer IRQ. For each rowState (or row pin), the current row is turned on, the previous row is turned off, and the columns are set by comparing the column mask value with the memory table value. The next rowState is then set. This example cycles sequentially from row one to row N and back to one. Before leaving the timer IRQ, gLedState is incremented to track the number of interrupts for each display period.

typedef enum {
    ROW_1,
    ROW_2,
    ROW_3
}rowNumber;

rowNumber rowState = ROW_1;

void LED_STATE_INST_IRQHandler(void) {
    switch (DL_TimerG_getPendingInterrupt(LED_STATE_INST)){
        case DL_TIMER_IIDX_ZERO:
            /* State machine to auto cycle from row 1 to row N and repeat */
            switch (rowState){
                case ROW_1:
                    /* Turn on ROW_1, Turn off ROW_3 */
                    DL_GPIO_clearPins(ROW_PORT, ROW_ROW_1_PIN);
                    DL_GPIO_setPins(ROW_PORT, ROW_ROW_3_PIN);

                    /* Set COLUMN values */
                    DL_GPIO_writePinsVal(COLUMN_PORT, COL_MASK, gLedMemoryTable[0]);
                    rowState = ROW_2;
                    break;
                case ROW_2:
                    /* Turn on ROW_2, Turn off ROW_1 */
                    DL_GPIO_clearPins(ROW_PORT, ROW_ROW_2_PIN);
                    DL_GPIO_setPins(ROW_PORT, ROW_ROW_1_PIN);

                    /* Set COLUMN values */
                    DL_GPIO_writePinsVal(COLUMN_PORT, COL_MASK, gLedMemoryTable[1]);
                    rowState = ROW_3;
                    break;
                case ROW_3:
                    /* Turn on ROW_3, Turn off ROW_2 */
                    DL_GPIO_clearPins(ROW_PORT, ROW_ROW_3_PIN);
                    DL_GPIO_setPins(ROW_PORT, ROW_ROW_2_PIN);

                    /* Set COLUMN values */
                    DL_GPIO_writePinsVal(COLUMN_PORT, COL_MASK, gLedMemoryTable[2]);
                    rowState = ROW_1;
                    break;
            }

            /* Increment LED_STATE */
            gLedState++;

            break;
        default:
            break;
    }
}

In the main code, all that is done is to write to the memory table every display period. This repeats indefinitely. This particular code uses binary to make determining which LED is on easier as the layout of 1s and 0s mimics the matrix layout. The binary value is 1 if an LED is on and 0 if an LED is off.

while(1){
    __WFI();
    /* Flash TI on repeat in half second increments */
    if (gLedState == LED_DISPLAY_PERIOD){ /* Display "T" for one display period */
        LED_updateTable(1, 0b111);
        LED_updateTable(2, 0b010);
        LED_updateTable(3, 0b010);
    } else if (gLedState == LED_DISPLAY_PERIOD*2){ /* Blank for one display period */
        LED_updateTable(1, 0b000);
        LED_updateTable(2, 0b000);
        LED_updateTable(3, 0b000);
    } else if (gLedState == LED_DISPLAY_PERIOD*3){ /* Display "I" for one display period */
        LED_updateTable(1, 0b111);
        LED_updateTable(2, 0b010);
        LED_updateTable(3, 0b111);
    } else if (gLedState == LED_DISPLAY_PERIOD*4){ /* Blank for one display period */
        LED_updateTable(1, 0b000);
        LED_updateTable(2, 0b000);
        LED_updateTable(3, 0b000);
    } else if (gLedState > LED_DISPLAY_PERIOD*4){ /* Reset gLedState and start over */
        gLedState = 0;
    }
}