Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions bsp/nxp/mcx/mcxa/frdm-mcxa366/board/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ menu "On-chip Peripheral Drivers"
endmenu

menu "Onboard Peripheral Drivers"
config BSP_USING_SLCD
bool "Enable onboard SLCD display"
default y
help
Enable FRDM-MCXA366 onboard segment LCD (6 digits).

config BSP_USING_ARDUINO
bool "Compatible with Arduino Ecosystem (RTduino)"
select PKG_USING_RTDUINO
Expand Down
28 changes: 28 additions & 0 deletions bsp/nxp/mcx/mcxa/frdm-mcxa366/board/MCUX_Config/board/pin_mux.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,3 +436,31 @@ void BOARD_InitPins(void)
/* PORT1_2 (pin 137) is configured as CAN0_TXD */
PORT_SetPinConfig(PORT1, 2U, &port1_2_pin137_config);
}

void BOARD_InitSLCDPins(void)
{
uint8_t pin;

/* LCD_P16~LCD_P31 are routed on PORT0_12~PORT0_27 (Alt9). */
const port_pin_config_t slcd_pin_config = {
.pullSelect = kPORT_PullDisable,
.pullValueSelect = kPORT_LowPullResistor,
.slewRate = kPORT_FastSlewRate,
.passiveFilterEnable = kPORT_PassiveFilterDisable,
.openDrainEnable = kPORT_OpenDrainDisable,
.driveStrength = kPORT_LowDriveStrength,
.driveStrength1 = kPORT_NormalDriveStrength,
.mux = kPORT_MuxAlt9,
.inputBuffer = kPORT_InputBufferEnable,
.invertInput = kPORT_InputNormal,
.lockRegister = kPORT_UnlockRegister,
};

CLOCK_EnableClock(kCLOCK_GatePORT0);
RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn);

for (pin = 12U; pin <= 27U; pin++)
{
PORT_SetPinConfig(PORT0, pin, &slcd_pin_config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ void BOARD_InitBootPins(void);
*/
void BOARD_InitPins(void);

/*!
* @brief Configures PORT0_12~PORT0_27 as LCD_P16~LCD_P31 for onboard SLCD.
*
*/
void BOARD_InitSLCDPins(void);

#if defined(__cplusplus)
}
#endif
Expand Down
7 changes: 5 additions & 2 deletions bsp/nxp/mcx/mcxa/frdm-mcxa366/board/ports/SConscript
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from building import *
import os

cwd = GetCurrentDir()
# add the general drivers.
src = Glob('*.c')
src = []
CPPPATH = [cwd]

if GetDepend(['BSP_USING_SLCD']):
src += ['drv_slcd.c']

group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)

list = os.listdir(cwd)
Expand Down
236 changes: 236 additions & 0 deletions bsp/nxp/mcx/mcxa/frdm-mcxa366/board/ports/drv_slcd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
* Copyright 2024-2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*
* Board-level SLCD helper for FRDM-MCXA366, built on NXP fsl_slcd.
*
* Segment mapping (8 bits per front-plane pair in num_matrix):
* 7 6 5 4 | 3 2 1 0
* E G F P | D C B A
*
* Front plane: digit6..digit1 use LCD_P27/P26 .. LCD_P17/P16
* Back plane: COM1..COM4 use LCD_P28..LCD_P31
*/

#include <rtthread.h>

#ifdef BSP_USING_SLCD

#include "drv_slcd.h"
#include "pin_mux.h"
#include "fsl_clock.h"
#include "fsl_reset.h"
#include "fsl_slcd.h"

#define BOARD_SLCD LCD0

#define SEGA 0x0001u
#define SEGB 0x0002u
#define SEGC 0x0004u
#define SEGD 0x0008u
#define SEGP 0x0100u
#define SEGF 0x0200u
#define SEGG 0x0400u
#define SEGE 0x0800u

/* Low byte -> pin_lo (A/B/C/D), high byte -> pin_hi (P/F/G/E). */
static const uint16_t num_matrix[] =
{
SEGA | SEGB | SEGC | SEGD | SEGE | SEGF, /* 0 */
SEGB | SEGC, /* 1 */
SEGA | SEGB | SEGG | SEGE | SEGD, /* 2 */
SEGA | SEGB | SEGG | SEGC | SEGD, /* 3 */
SEGF | SEGG | SEGB | SEGC, /* 4 */
SEGA | SEGF | SEGG | SEGC | SEGD, /* 5 */
SEGA | SEGF | SEGE | SEGD | SEGC | SEGG, /* 6 */
SEGA | SEGB | SEGC, /* 7 */
SEGA | SEGB | SEGC | SEGD | SEGE | SEGF | SEGG, /* 8 */
SEGA | SEGF | SEGG | SEGB | SEGC | SEGD, /* 9 */
0 /* space / blank */
};

/* digit 1..6 -> low front-plane pin (high pin is low+1) */
static const uint8_t digit_pin_lo[] = {0, 16, 18, 20, 22, 24, 26};

/* SLCD_Px point -> front-plane pin (phase A / SEGP) */
static const uint8_t point_pin[] =
{
23, /* P1 */
21, /* P2 */
19, /* P3 */
25, /* P4 */
27, /* P5 */
17, /* P6 */
};

static rt_bool_t g_slcd_inited = RT_FALSE;

static void slcd_set_digit_segments(uint8_t digit, uint16_t seg)
{
uint8_t pin_lo;

if ((digit < 1U) || (digit > 6U))
{
return;
}

pin_lo = digit_pin_lo[digit];
SLCD_SetFrontPlaneSegments(BOARD_SLCD, pin_lo, (uint8_t)(seg & 0xFFU));
SLCD_SetFrontPlaneSegments(BOARD_SLCD, pin_lo + 1U, (uint8_t)((seg >> 8) & 0xFFU));
}

int rt_hw_slcd_init(void)
{
slcd_config_t config;

if (g_slcd_inited)
{
return RT_EOK;
}

BOARD_InitSLCDPins();

/* SLCD function clock on MCXA366. */
CLOCK_SetupFRO16KClocking(kCLKE_16K_COREMAIN);
RESET_ReleasePeripheralReset(kSLCD0_RST_SHIFT_RSTn);

SLCD_GetDefaultConfig(&config);
config.dutyCycle = kSLCD_1Div4DutyCycle;
config.slcdLowPinEnabled = 0xFFFF0000U; /* LCD_P16~P31 */
config.slcdHighPinEnabled = 0U;
config.backPlaneLowPin = 0xF0000000U; /* LCD_P28~P31 */
config.backPlaneHighPin = 0U;
config.faultConfig = RT_NULL;
SLCD_Init(BOARD_SLCD, &config);

SLCD_SetBackPlanePhase(BOARD_SLCD, 28U, kSLCD_PhaseAActivate);
SLCD_SetBackPlanePhase(BOARD_SLCD, 29U, kSLCD_PhaseBActivate);
SLCD_SetBackPlanePhase(BOARD_SLCD, 30U, kSLCD_PhaseCActivate);
SLCD_SetBackPlanePhase(BOARD_SLCD, 31U, kSLCD_PhaseDActivate);

SLCD_StartDisplay(BOARD_SLCD);

g_slcd_inited = RT_TRUE;
return RT_EOK;
}

void rt_hw_slcd_display_all(void)
{
uint8_t pin;

for (pin = 16U; pin <= 27U; pin++)
{
SLCD_SetFrontPlaneSegments(BOARD_SLCD, pin,
(uint8_t)(kSLCD_PhaseAActivate | kSLCD_PhaseBActivate |
kSLCD_PhaseCActivate | kSLCD_PhaseDActivate));
}
}

void rt_hw_slcd_clear(void)
{
uint8_t pin;

for (pin = 16U; pin <= 27U; pin++)
{
SLCD_SetFrontPlaneSegments(BOARD_SLCD, pin, (uint8_t)kSLCD_NoPhaseActivate);
}
}

void rt_hw_slcd_display_num(uint8_t digit, uint8_t num)
{
uint16_t seg = (num <= 9U) ? num_matrix[num] : num_matrix[10];

slcd_set_digit_segments(digit, seg);
}

void rt_hw_slcd_display_string(const char *str)
{
uint8_t digit;
uint8_t num;
uint8_t points = 0U;

if (str == RT_NULL)
{
return;
}

for (digit = 6U; digit >= 1U; digit--)
{
while ((*str == ':') || (*str == '.'))
{
if (*str == ':')
{
points |= SLCD_COLON;
}
else
{
points |= SLCD_DOT;
}
str++;
}

if (*str == '\0')
{
num = 10U;
}
else if (*str == ' ')
{
num = 10U;
str++;
}
else
{
num = (uint8_t)(*str - '0');
str++;
if (num > 9U)
{
num = 10U;
}
}
rt_hw_slcd_display_num(digit, num);
if (digit == 1U)
{
break;
}
}

if (points != 0U)
{
rt_hw_slcd_display_point(points);
}
}

void rt_hw_slcd_display_time(uint8_t hour, uint8_t minute)
{
char buf[8];

if (hour > 99U)
{
hour = 99U;
}
if (minute > 99U)
{
minute = 99U;
}

rt_snprintf(buf, sizeof(buf), "%02u:%02u", hour, minute);
rt_hw_slcd_clear();
rt_hw_slcd_display_string(buf);
}

void rt_hw_slcd_display_point(uint8_t point)
{
uint8_t i;

for (i = 0U; i < 6U; i++)
{
if (point & (1U << i))
{
SLCD_SetFrontPlaneOnePhase(BOARD_SLCD, point_pin[i], kSLCD_PhaseAIndex, true);
}
}
}

#endif /* BSP_USING_SLCD */
46 changes: 46 additions & 0 deletions bsp/nxp/mcx/mcxa/frdm-mcxa366/board/ports/drv_slcd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
* Copyright 2024-2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*
* FRDM-MCXA366 onboard segment LCD helper (wraps NXP fsl_slcd).
* Digit layout (left -> right): digit6 digit5 digit4 digit3 digit2 digit1
* Points: P1/P2/P3 (upper) and P4/P5/P6 (lower).
*/

#ifndef __DRV_SLCD_H__
#define __DRV_SLCD_H__

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#define SLCD_P1 0x01u
#define SLCD_P2 0x02u
#define SLCD_P3 0x04u
#define SLCD_P4 0x08u
#define SLCD_P5 0x10u
#define SLCD_P6 0x20u

/* Colon between digit5 and digit4 (HH:MM / MM:SS). */
#define SLCD_COLON (SLCD_P1 | SLCD_P4)
/* Decimal point between digit3 and digit2. */
#define SLCD_DOT (SLCD_P6)

int rt_hw_slcd_init(void);
void rt_hw_slcd_clear(void);
void rt_hw_slcd_display_all(void);
void rt_hw_slcd_display_num(uint8_t digit, uint8_t num);
void rt_hw_slcd_display_string(const char *str);
void rt_hw_slcd_display_point(uint8_t point);
/* Show HH:MM, e.g. rt_hw_slcd_display_time(12, 30) -> 12:30 */
void rt_hw_slcd_display_time(uint8_t hour, uint8_t minute);

#ifdef __cplusplus
}
#endif

#endif /* __DRV_SLCD_H__ */
Loading