609 lines
17 KiB
C
609 lines
17 KiB
C
/**
|
|
* @file X-NUCLEO-53L1A1.c
|
|
*
|
|
* implement X-NUCLEO-53L1A1 Nucleo BSP
|
|
*/
|
|
|
|
#include "main.h"
|
|
#include <string.h>
|
|
#include "X-NUCLEO-53L1A1.h"
|
|
|
|
#include "stm32wlxx_hal.h"
|
|
|
|
|
|
#ifndef HAL_I2C_MODULE_ENABLED
|
|
#define HAL_I2C_MODULE_ENABLED
|
|
#pragma message("hal conf should enable i2c")
|
|
#endif
|
|
|
|
/* when not customized by application define dummy one */
|
|
#ifndef XNUCLEO53L1A1_GetI2cBus
|
|
/**
|
|
* macro that can be overloaded by user to enforce i2c sharing in RTOS context
|
|
*/
|
|
#define XNUCLEO53L1A1_GetI2cBus(...) (void)0
|
|
#endif
|
|
|
|
#ifndef XNUCLEO53L1A1_PutI2cBus
|
|
/** macro can be overloaded by user to enforce i2c sharing in RTOS context
|
|
*/
|
|
# define XNUCLEO53L1A1_PutI2cBus(...) (void)0
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
* Expander 0 i2c address[7..0] format
|
|
*/
|
|
#define I2cExpAddr0 ((int)(0x43*2))
|
|
/**
|
|
* Expander 1 i2c address[7..0] format
|
|
*/
|
|
#define I2cExpAddr1 ((int)(0x42*2))
|
|
/** @} XNUCLEO53L1A1_I2CExpanders*/
|
|
|
|
|
|
/**
|
|
* GPIO monitor pin state register
|
|
* 16 bit register LSB at lowest offset (little endian)
|
|
*/
|
|
#define GPMR 0x10
|
|
/**
|
|
* STMPE1600 GPIO set pin state register
|
|
* 16 bit register LSB at lowest offset (little endian)
|
|
*/
|
|
#define GPSR 0x12
|
|
/**
|
|
* STMPE1600 GPIO set pin direction register
|
|
* 16 bit register LSB at lowest offset
|
|
*/
|
|
#define GPDR 0x14
|
|
|
|
|
|
/** @} */ /* defgroup XNUCLEO53L1A1_Board */
|
|
|
|
|
|
/****************************************************
|
|
*@defgroup XNUCLEO53L1A1_globals
|
|
*@{
|
|
*/
|
|
|
|
/**
|
|
* i2c handle to be use of all i2c access
|
|
* end user shall provide it to
|
|
* can be @a XNUCLEO53L1A1_I2C1Configure() @sa XNUCLEO53L1A1_usage
|
|
* @warning do not use any XNUCLEO53L1A1_xxx prior to a first init with valid i2c handle
|
|
*/
|
|
I2C_HandleTypeDef XNUCLEO53L1A1_hi2c;
|
|
|
|
|
|
/**
|
|
* cache the full set of expanded GPIO values to avoid i2c reading
|
|
*/
|
|
static union CurIOVal_u {
|
|
uint8_t bytes[4]; /*!< 4 bytes array i/o view */
|
|
uint32_t u32; /*!< single dword i/o view */
|
|
}
|
|
/** cache the extended IO values */
|
|
CurIOVal;
|
|
|
|
/**
|
|
* lookup table for for digit to bit position in @a CurIOVal u32
|
|
*/
|
|
static int DisplayBitPos[4]={0, 7, 16, 16+7};
|
|
|
|
/** @} XNUCLEO53L1A1_globals*/
|
|
|
|
/* Forward definition of private function */
|
|
|
|
static int _ExpanderRd(int I2cExpAddr, int index, uint8_t *data, int n_data);
|
|
static int _ExpanderWR(int I2cExpAddr, int index, uint8_t *data, int n_data);
|
|
static int _ExpandersSetAllIO(void);
|
|
|
|
/**
|
|
* Expansion board i2c bus recovery
|
|
*
|
|
* We may get reset in middle of an i2c access (h/w reset button, debug or f/w load)
|
|
* hence some agent on bus may be in middle of a transaction and can create issue or even prevent starting (SDA is low)
|
|
* this routine does use gpio to manipulate and recover i2c bus line in all cases.
|
|
*/
|
|
static void _I2cFailRecover(){
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
int i, nRetry=0;
|
|
|
|
|
|
// We can't assume bus state based on SDA and SCL state (we may be in a data or NAK bit so SCL=SDA=1)
|
|
// by setting SDA high and toggling SCL at least 10 time we ensure whatever agent and state
|
|
// all agent should end up seeing a "stop" and bus get back to an known idle i2c bus state
|
|
|
|
// Enable I/O
|
|
__GPIOA_CLK_ENABLE();
|
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
|
|
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
|
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
//TODO we could do this faster by not using HAL delay 1ms for clk timing
|
|
do{
|
|
for( i=0; i<10; i++){
|
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
|
|
HAL_Delay(1);
|
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
|
|
HAL_Delay(1);
|
|
}
|
|
// if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 ){
|
|
// static int RetryRecover;
|
|
// RetryRecover++;
|
|
// }
|
|
}while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == 0 && nRetry++<7);
|
|
|
|
if( HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == 0 ){
|
|
__GPIOB_CLK_ENABLE();
|
|
//We are still in bad i2c state warm user by blinking led but stay here
|
|
GPIO_InitStruct.Pin = LED1_Pin ;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
HAL_GPIO_Init(LED3_GPIO_Port, &GPIO_InitStruct);
|
|
do{
|
|
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);
|
|
HAL_Delay(33);
|
|
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET);
|
|
HAL_Delay(33);
|
|
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);
|
|
HAL_Delay(33);
|
|
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET);
|
|
HAL_Delay(33*20);
|
|
}while(1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int XNUCLEO53L1A1_I2C2Configure() {
|
|
int status;
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
|
|
_I2cFailRecover();
|
|
|
|
/* Peripheral clock enable */
|
|
__GPIOA_CLK_ENABLE();
|
|
__I2C2_CLK_ENABLE();
|
|
|
|
/**I2C1 GPIO Configuration\n
|
|
PB8 ------> I2C1_SCL\n
|
|
PB9 ------> I2C1_SDA
|
|
*/
|
|
GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_11;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
|
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
|
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
|
|
XNUCLEO53L1A1_hi2c.Instance = I2C2;
|
|
//XNUCLEO53L1A1_hi2c.Init.Timing = 0x00300F38; /* set 400KHz fast mode i2c*/
|
|
XNUCLEO53L1A1_hi2c.Init.Timing = 0x2010091A; //0x2010091A = 400K Fast Mode, 0x20303E5D, 100K Standard mode, 0x20000209 Fast Mode Plus, 1Mbps
|
|
|
|
XNUCLEO53L1A1_hi2c.Init.OwnAddress1 = 0;
|
|
XNUCLEO53L1A1_hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
|
XNUCLEO53L1A1_hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
|
|
XNUCLEO53L1A1_hi2c.Init.OwnAddress2 = 0;
|
|
XNUCLEO53L1A1_hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
|
|
XNUCLEO53L1A1_hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
|
|
status = HAL_I2C_Init(&XNUCLEO53L1A1_hi2c);
|
|
return status;
|
|
}
|
|
|
|
int XNUCLEO53L1A1_SetIntrStateId(int EnableIntr, int DevNo){
|
|
int status;
|
|
IRQn_Type IntrNo;
|
|
int IntrPin;
|
|
|
|
|
|
switch( DevNo ){
|
|
case XNUCLEO53L1A1_DEV_CENTER :
|
|
case 'c' :
|
|
IntrNo = VL53L1A1_GPIO1_C_INTx;
|
|
IntrPin= VL53L1A1_GPIO1_C_GPIO_PIN;
|
|
status = 0;
|
|
break;
|
|
|
|
case XNUCLEO53L1A1_DEV_LEFT :
|
|
case 'l' :
|
|
|
|
break;
|
|
case 'r' :
|
|
case XNUCLEO53L1A1_DEV_RIGHT :
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
XNUCLEO53L1A1_ErrLog("Invalid DevNo %d",DevNo);
|
|
status = -1;
|
|
goto done;
|
|
}
|
|
|
|
if( EnableIntr ){
|
|
__HAL_GPIO_EXTI_CLEAR_IT(IntrPin);
|
|
NVIC_ClearPendingIRQ(IntrNo);
|
|
HAL_NVIC_EnableIRQ(IntrNo);
|
|
/**
|
|
* @note When enabling interrupt end user shall check actual state of the line and soft trigger event if active
|
|
* Alternatively user can use API and device feature to clear device Interrupt status to possibly generates a new edge.
|
|
* on shared pin configuration this must be repeated for all device.
|
|
* The same shall be done after clearing a condition in device and interrupt remain active.
|
|
*/
|
|
}
|
|
else{
|
|
HAL_NVIC_DisableIRQ(IntrNo);
|
|
__HAL_GPIO_EXTI_CLEAR_IT(IntrPin);
|
|
NVIC_ClearPendingIRQ(IntrNo);
|
|
}
|
|
|
|
done:
|
|
return status;
|
|
}
|
|
|
|
|
|
int XNUCLEO53L1A1_Init(void) {
|
|
int status;
|
|
// uint8_t ExpanderData[2];
|
|
// XNUCLEO53L1A1_USART2_UART_Init();
|
|
status = XNUCLEO53L1A1_I2C2Configure();
|
|
return status;
|
|
}
|
|
|
|
|
|
int XNUCLEO53L1A1_GetPB1(int *state) {
|
|
int status;
|
|
uint8_t PortValue;
|
|
status= _ExpanderRd(I2cExpAddr1, GPMR+1, &PortValue,1);
|
|
if( status == 0){
|
|
if( PortValue&=0x40 )
|
|
PortValue=1;
|
|
else
|
|
PortValue=0;
|
|
}
|
|
else{
|
|
XNUCLEO53L1A1_ErrLog("i/o error");
|
|
}
|
|
*state = PortValue;
|
|
return status;
|
|
}
|
|
|
|
int XNUCLEO53L1A1_ResetId(int DevNo, int state) {
|
|
int status;
|
|
switch( DevNo ){
|
|
case XNUCLEO53L1A1_DEV_CENTER :
|
|
case 'c' :
|
|
CurIOVal.bytes[3]&=~0x80; /* bit 15 expender 1 => byte #3 */
|
|
if( state )
|
|
CurIOVal.bytes[3]|=0x80; /* bit 15 expender 1 => byte #3 */
|
|
status= _ExpanderWR(I2cExpAddr1, GPSR+1, &CurIOVal.bytes[3], 1);
|
|
break;
|
|
case XNUCLEO53L1A1_DEV_LEFT :
|
|
case 'l' :
|
|
CurIOVal.bytes[1]&=~0x40; /* bit 14 expender 0 => byte #1*/
|
|
if( state )
|
|
CurIOVal.bytes[1]|=0x40; /* bit 14 expender 0 => byte #1*/
|
|
status= _ExpanderWR(I2cExpAddr0, GPSR+1, &CurIOVal.bytes[1], 1);
|
|
break;
|
|
case 'r' :
|
|
case XNUCLEO53L1A1_DEV_RIGHT :
|
|
CurIOVal.bytes[1]&=~0x80; /* bit 15 expender 0 => byte #1 */
|
|
if( state )
|
|
CurIOVal.bytes[1]|=0x80; /* bit 15 expender 0 => byte #1*/
|
|
status= _ExpanderWR(I2cExpAddr0, GPSR+1, &CurIOVal.bytes[1], 1);
|
|
break;
|
|
default:
|
|
XNUCLEO53L1A1_ErrLog("Invalid DevNo %d",DevNo);
|
|
status = -1;
|
|
goto done;
|
|
}
|
|
//error with valid id
|
|
if( status ){
|
|
XNUCLEO53L1A1_ErrLog("expander i/o error for DevNo %d state %d ",DevNo, state);
|
|
}
|
|
done:
|
|
return status;
|
|
}
|
|
|
|
|
|
void VL53L1A1_EXTI_IOConfigure(int DevNo, int IntPriority, int SubPriority){
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
|
|
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
|
|
GPIO_InitStruct.Pull = VL53L1A1_INTR_PIN_PUPD;
|
|
|
|
switch (DevNo ) {
|
|
case XNUCLEO53L1A1_DEV_CENTER:
|
|
case 'c':
|
|
VL53L1A1_GPIO1_C_CLK_ENABLE();
|
|
/*Configure GPIO pin : PA4 */
|
|
GPIO_InitStruct.Pin = VL53L1A1_GPIO1_C_GPIO_PIN;
|
|
|
|
XNUCLEO53L1A1_SetIntrStateId(1,XNUCLEO53L1A1_DEV_CENTER);
|
|
HAL_GPIO_Init(VL53L1A1_GPIO1_C_GPIO_PORT, &GPIO_InitStruct);
|
|
HAL_NVIC_SetPriority((IRQn_Type)VL53L1A1_GPIO1_C_GPIO_PIN, IntPriority, SubPriority);
|
|
break;
|
|
|
|
#if VL53L1A1_GPIO1_SHARED == 0
|
|
case XNUCLEO53L1A1_DEV_LEFT:
|
|
case 'l':
|
|
break;
|
|
|
|
case XNUCLEO53L1A1_DEV_RIGHT:
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void VL53L1A1_EXTI_IOUnconfigure(int DevNo){
|
|
switch (DevNo ) {
|
|
case XNUCLEO53L1A1_DEV_CENTER:
|
|
case 'c':
|
|
//XNUCLEO53L1A1_SetIntrStateId(0,XNUCLEO53L1A1_DEV_TOP);
|
|
HAL_GPIO_DeInit(VL53L1A1_GPIO1_C_GPIO_PORT, VL53L1A1_GPIO1_C_GPIO_PIN);
|
|
__HAL_GPIO_EXTI_CLEAR_IT(VL53L1A1_GPIO1_C_GPIO_PIN);
|
|
break;
|
|
|
|
#if VL53L1A1_GPIO1_SHARED == 0
|
|
case XNUCLEO53L1A1_DEV_LEFT:
|
|
case 'l':
|
|
// XNUCLEO53L1A1_SetIntrStateId(0,XNUCLEO53L1A1_DEV_LEFT);
|
|
HAL_GPIO_DeInit(VL53L1A1_GPIO1_L_GPIO_PORT, VL53L1A1_GPIO1_L_GPIO_PIN);
|
|
__HAL_GPIO_EXTI_CLEAR_IT(VL53L1A1_GPIO1_L_GPIO_PIN);
|
|
break;
|
|
|
|
case XNUCLEO53L1A1_DEV_RIGHT:
|
|
case 'r':
|
|
HAL_GPIO_DeInit(VL53L1A1_GPIO1_R_GPIO_PORT, VL53L1A1_GPIO1_R_GPIO_PIN);
|
|
__HAL_GPIO_EXTI_CLEAR_IT(VL53L1A1_GPIO1_R_GPIO_PIN);
|
|
//XNUCLEO53L1A1_SetIntrStateId(0,XNUCLEO53L1A1_DEV_RIGHT);
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
/**
|
|
* Set all i2c expended gpio in one go
|
|
* @return i/o operation status
|
|
*/
|
|
static int _ExpandersSetAllIO(void){
|
|
int status;
|
|
status = _ExpanderWR(I2cExpAddr0, GPSR, &CurIOVal.bytes[0], 2);
|
|
if( status ){
|
|
goto done_err;
|
|
}
|
|
status = _ExpanderWR(I2cExpAddr1, GPSR, &CurIOVal.bytes[2], 2);
|
|
done_err:
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* STMPE1600 i2c Expender register read
|
|
* @param I2cExpAddr Expender address
|
|
* @param index register index
|
|
* @param data read data buffer
|
|
* @param n_data number of byte to read
|
|
* @return of if ok else i2c I/O operation status
|
|
*/
|
|
static int _ExpanderRd(int I2cExpAddr, int index, uint8_t *data, int n_data) {
|
|
|
|
int status;
|
|
uint8_t RegAddr;
|
|
RegAddr = index;
|
|
XNUCLEO53L1A1_GetI2cBus();
|
|
do {
|
|
status = HAL_I2C_Master_Transmit(&XNUCLEO53L1A1_hi2c, I2cExpAddr, &RegAddr, 1, 100);
|
|
if (status)
|
|
break;
|
|
status = HAL_I2C_Master_Receive(&XNUCLEO53L1A1_hi2c, I2cExpAddr, data, n_data, n_data * 100);
|
|
} while (0);
|
|
XNUCLEO53L1A1_PutI2cBus();
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* STMPE1600 i2c Expender register write
|
|
* @param I2cExpAddr Expender address
|
|
* @param index register index
|
|
* @param data data buffer
|
|
* @param n_data number of byte to write
|
|
* @return of if ok else i2c I/O operation status
|
|
*/
|
|
static int _ExpanderWR(int I2cExpAddr, int index, uint8_t *data, int n_data) {
|
|
|
|
int status;
|
|
uint8_t RegAddr[0x10];
|
|
RegAddr[0] = index;
|
|
memcpy(RegAddr + 1, data, n_data);
|
|
XNUCLEO53L1A1_GetI2cBus();
|
|
status = HAL_I2C_Master_Transmit(&XNUCLEO53L1A1_hi2c, I2cExpAddr, RegAddr, n_data + 1, 100);
|
|
XNUCLEO53L1A1_PutI2cBus();
|
|
return status;
|
|
}
|
|
|
|
|
|
/**
|
|
* @defgroup XNUCLEO53L1A1_7Segment 7 segment display
|
|
*
|
|
* macro use for human readable segment building
|
|
* @code
|
|
* --s0--
|
|
* s s
|
|
* 5 1
|
|
* --s6--
|
|
* s s
|
|
* 4 2
|
|
* --s3-- . s7 (dp)
|
|
* @endcode
|
|
*
|
|
* @{
|
|
*/
|
|
/** decimal point bit mapping* */
|
|
#define DP (1<<7)
|
|
|
|
//VL6180 shield
|
|
//#define S0 (1<<0)
|
|
//#define S1 (1<<1)
|
|
//#define S2 (1<<2)
|
|
//#define S3 (1<<3)
|
|
//#define S4 (1<<4)
|
|
//#define S5 (1<<5)
|
|
//#define S6 (1<<6)
|
|
|
|
/** sgement s0 bit mapping*/
|
|
#define S0 (1<<3)
|
|
/** sgement s1 bit mapping*/
|
|
#define S1 (1<<5)
|
|
/** sgement s2 bit mapping*/
|
|
#define S2 (1<<6)
|
|
/** sgement s3 bit mapping*/
|
|
#define S3 (1<<4)
|
|
/** sgement s4 bit mapping*/
|
|
#define S4 (1<<0)
|
|
/** sgement s5 bit mapping*/
|
|
#define S5 (1<<1)
|
|
/** sgement s6 bit mapping*/
|
|
#define S6 (1<<2)
|
|
|
|
/**
|
|
* build a character by defining the non lighted segment (not one and no DP)
|
|
*
|
|
* @param ... literal sum and or combine of any macro to define any segment #S0 .. #S6
|
|
*
|
|
* example '9' is all segment on but S4
|
|
* @code
|
|
* ['9']= NOT_7_NO_DP(S4),
|
|
* @endcode
|
|
*/
|
|
#define NOT_7_NO_DP( ... ) (uint8_t) ~( __VA_ARGS__ + DP )
|
|
|
|
/**
|
|
* Ascii to 7 segment lookup table
|
|
*
|
|
* Most common character are supported and follow http://www.twyman.org.uk/Fonts/
|
|
* few extra special \@ ^~ ... etc are present for specific demo purpose
|
|
*/
|
|
static const uint8_t ascii_to_display_lut[256]={
|
|
[' ']= 0,
|
|
['-']= S6,
|
|
['_']= S3,
|
|
['=']= S3+S6,
|
|
['~']= S0+S3+S6, /* 3 h bar */
|
|
['^']= S0, /* use as top bar */
|
|
|
|
['?']= NOT_7_NO_DP(S5+S3+S2),
|
|
['*']= NOT_7_NO_DP(),
|
|
['[']= S0+S3+S4+S5,
|
|
[']']= S0+S3+S2+S1,
|
|
['@']= S0+S3,
|
|
|
|
['0']= NOT_7_NO_DP(S6),
|
|
['1']= S1+S2,
|
|
['2']= S0+S1+S6+S4+S3,
|
|
['3']= NOT_7_NO_DP(S4+S5),
|
|
['4']= S5+S1+S6+S2,
|
|
['5']= NOT_7_NO_DP(S1+S4),
|
|
['6']= NOT_7_NO_DP(S1),
|
|
['7']= S0+S1+S2,
|
|
['8']= NOT_7_NO_DP(0),
|
|
['9']= NOT_7_NO_DP(S4),
|
|
|
|
['a']= S2+ S3+ S4+ S6 ,
|
|
['b']= NOT_7_NO_DP(S0+S1),
|
|
['c']= S6+S4+S3,
|
|
['d']= NOT_7_NO_DP(S0+S5),
|
|
['e']= NOT_7_NO_DP(S2),
|
|
['f']= S6+S5+S4+S0, /* same as F */
|
|
['g']= NOT_7_NO_DP(S4), /* same as 9 */
|
|
['h']= S6+S5+S4+S2,
|
|
['i']= S4,
|
|
['j']= S1+S2+S3+S4,
|
|
['k']= S6+S5+S4+S2, /* a h */
|
|
['l']= S3+S4,
|
|
['m']= S0+S4+S2, /* same as */
|
|
['n']= S2+S4+S6,
|
|
['o']= S6+S4+S3+S2,
|
|
['p']= NOT_7_NO_DP(S3+S2), // same as P
|
|
['q']= S0+S1+S2+S5+S6,
|
|
['r']= S4+S6,
|
|
['s']= NOT_7_NO_DP(S1+S4),
|
|
['t']= NOT_7_NO_DP(S0+S1+S2),
|
|
['u']= S4+S3+S2+S5+S1, // U
|
|
['v']= S4+S3+S2, // is u but u use U
|
|
['w']= S1+S3+S5,
|
|
['x']= NOT_7_NO_DP(S0+S3), // similar to H
|
|
['y']= NOT_7_NO_DP(S0+S4),
|
|
['z']= S0+S1+S6+S4+S3, // same as 2
|
|
|
|
['A']= NOT_7_NO_DP(S3),
|
|
['B']= NOT_7_NO_DP(S0+S1), /* as b */
|
|
['C']= S0+S3+S4+S5, // same as [
|
|
['E']= NOT_7_NO_DP(S1+S2),
|
|
['F']= S6+S5+S4+S0,
|
|
['G']= NOT_7_NO_DP(S4), /* same as 9 */
|
|
['H']= NOT_7_NO_DP(S0+S3),
|
|
['I']= S1+S2,
|
|
['J']= S1+S2+S3+S4,
|
|
['K']= NOT_7_NO_DP(S0+S3), /* same as H */
|
|
['L']= S3+S4+S5,
|
|
['M']= S0+S4+S2, /* same as m*/
|
|
['N']= S2+S4+S6, /* same as n*/
|
|
['O']= NOT_7_NO_DP(S6),
|
|
['P']= NOT_7_NO_DP(S3+S2),
|
|
['Q']= NOT_7_NO_DP(S3+S2),
|
|
['R']= S4+S6,
|
|
['S']= NOT_7_NO_DP(S1+S4), /* sasme as 5 */
|
|
['T']= NOT_7_NO_DP(S0+S1+S2), /* sasme as t */
|
|
['U']= NOT_7_NO_DP(S6+S0),
|
|
['V']= S4+S3+S2, // is u but u use U
|
|
['W']= S1+S3+S5,
|
|
['X']= NOT_7_NO_DP(S0+S3), // similar to H
|
|
['Y']= NOT_7_NO_DP(S0+S4),
|
|
['Z']= S0+S1+S6+S4+S3, // same as 2
|
|
};
|
|
|
|
#undef S0
|
|
#undef S1
|
|
#undef S2
|
|
#undef S3
|
|
#undef S4
|
|
#undef S5
|
|
#undef S6
|
|
#undef DP
|
|
|
|
/** @} */
|
|
|
|
int XNUCLEO53L1A1_SetDisplayString(const char *str) {
|
|
int status;
|
|
uint32_t Segments;
|
|
int BitPos;
|
|
int i;
|
|
|
|
for( i=0; i<4 && str[i]!=0; i++){
|
|
Segments = (uint32_t)ascii_to_display_lut[(uint8_t)str[i]];
|
|
Segments =(~Segments)&0x7F;
|
|
BitPos=DisplayBitPos[i];
|
|
CurIOVal.u32 &=~(0x7F<<BitPos);
|
|
CurIOVal.u32 |= Segments<<BitPos;
|
|
}
|
|
/* clear unused digit */
|
|
for( ; i<4;i++){
|
|
BitPos=DisplayBitPos[i];
|
|
CurIOVal.u32 |=0x7F<<BitPos;
|
|
}
|
|
status = _ExpandersSetAllIO();
|
|
if( status ){
|
|
XNUCLEO53L1A1_ErrLog("Set i/o");
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @} XNUCLEO53L1A1_top
|
|
*/
|