Skip to content

Commit c119b9e

Browse files
committed
Add spi/i2c wrappers, gd32 GPIO & i2c fixes
Introduce modern C++ wrapper headers for SPI and I2C (lib-gd32/include/spi.h, lib-gd32/include/i2c.h) that wrap existing gd32_* APIs and provide a unified namespace-based interface. Update SpiLcd to use the new spi namespace and hal_gpio, replacing previous FUNC_PREFIX/SPi calls. Add 16-bit I2C register write support (prototypes in gd32_i2c.h and implementation in gd32_i2c.cpp). Rename AT24Cxx member/constructor to device_address and update usages to use the new name. Replace macro GPIO helpers with constexpr conversion helpers and fix Gd32GpioToPeriph logic to use the computed port index. Remove legacy hal_spi headers from lib-hal in favor of the new spi abstraction. Minor formatting and API alignment changes throughout.
1 parent 1de8d0f commit c119b9e

10 files changed

Lines changed: 312 additions & 175 deletions

File tree

lib-display/include/spi/spilcd.h

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,20 @@
2828

2929
#include "timing.h"
3030
#include "spi/config.h"
31-
#include "hal_spi.h"
31+
#include "spi.h"
32+
#include "hal_gpio.h"
3233
#include "firmware/debug/debug_debug.h"
3334

34-
#if defined CONFIG_LCD_SPI_BITBANG
35-
#define SPI_PREFIX(x) FUNC_PREFIX(Bitbang##x);
36-
#else
37-
#define SPI_PREFIX(x) FUNC_PREFIX(x);
38-
#endif
39-
4035
class SpiLcd {
4136
public:
4237
explicit SpiLcd(uint32_t cs = 0) : cs_(cs) {
4338
DEBUG_ENTRY();
4439
DEBUG_PRINTF("cs=%u", cs);
4540

46-
SPI_PREFIX(SpiBegin());
47-
SPI_PREFIX(SpiChipSelect(SPI_CS_NONE));
48-
SPI_PREFIX(SpiSetSpeedHz(20000000));
49-
SPI_PREFIX(SpiSetDataMode(SPI_MODE0));
41+
spi::Begin();
42+
spi::ChipSelect(spi::kCsNone);
43+
spi::SetSpeedHz(20000000);
44+
spi::SetDataMode(spi::kMode0);
5045

5146
#if defined(SPI_LCD_RST_GPIO)
5247
FUNC_PREFIX(GpioFsel(SPI_LCD_RST_GPIO, GPIO_FSEL_OUTPUT));
@@ -89,14 +84,14 @@ class SpiLcd {
8984
void WriteCommand(uint8_t data) {
9085
ClearCS();
9186
ClearDC();
92-
SPI_PREFIX(SpiWritenb(reinterpret_cast<char*>(&data), 1));
87+
spi::Writenb(reinterpret_cast<char*>(&data), 1);
9388
SetCS();
9489
}
9590

9691
void WriteData(const uint8_t* data, uint32_t length) {
9792
ClearCS();
9893
SetDC();
99-
SPI_PREFIX(SpiWritenb(reinterpret_cast<const char*>(data), length));
94+
spi::Writenb(reinterpret_cast<const char*>(data), length);
10095
SetCS();
10196
}
10297

@@ -109,27 +104,29 @@ class SpiLcd {
109104
void WriteDataByte(uint8_t data) {
110105
ClearCS();
111106
SetDC();
112-
SPI_PREFIX(SpiWritenb(reinterpret_cast<char*>(&data), 1));
107+
spi::Writenb(reinterpret_cast<char*>(&data), 1);
113108
SetCS();
114109
}
115110

116111
void WriteDataWord(uint16_t data) {
117112
ClearCS();
118113
SetDC();
119-
SPI_PREFIX(SpiWrite(data));
114+
spi::Write(data);
120115
SetCS();
121116
}
122117

123118
void WriteDataStart(uint8_t* data, uint32_t length) {
124119
ClearCS();
125120
SetDC();
126-
SPI_PREFIX(SpiWritenb(reinterpret_cast<char*>(data), length));
121+
spi::Writenb(reinterpret_cast<char*>(data), length);
127122
}
128123

129-
void WriteDataContinue(uint8_t* data, uint32_t length) { SPI_PREFIX(SpiWritenb(reinterpret_cast<char*>(data), length)); }
124+
void WriteDataContinue(uint8_t* data, uint32_t length) {
125+
spi::Writenb(reinterpret_cast<char*>(data), length);
126+
}
130127

131128
void WriteDataEnd(uint8_t* data, uint32_t length) {
132-
SPI_PREFIX(SpiWritenb(reinterpret_cast<char*>(data), length));
129+
spi::Writenb(reinterpret_cast<char*>(data), length);
133130
SetCS();
134131
}
135132

lib-flash/include/i2c/at24cxx.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ class AT24Cxx {
8888
/**
8989
* @brief Constructor for AT24Cxx.
9090
*
91-
* @param nSlaveAddress I2C slave address of the EEPROM device.
91+
* @param device_address I2C slave address of the EEPROM device.
9292
*/
93-
AT24Cxx(uint8_t nSlaveAddress) : m_nSlaveAddress(nSlaveAddress) {
93+
AT24Cxx(uint8_t device_address) : m_device_address(device_address) {
9494
static_assert(IsValidType(), "Invalid type specified for AT24Cxx.");
95-
m_IsConnected = FUNC_PREFIX(I2cIsConnected(m_nSlaveAddress, 400000));;
95+
m_IsConnected = FUNC_PREFIX(I2cIsConnected(m_device_address, 400000));;
9696
}
9797

9898
/** @brief Checks if the EEPROM device is connected. */
@@ -102,7 +102,7 @@ class AT24Cxx {
102102

103103
/** @brief Returns the I2C address of the EEPROM device. */
104104
uint8_t GetAddress() const {
105-
return m_nSlaveAddress;
105+
return m_device_address;
106106
}
107107

108108
/** @brief Returns the size of the EEPROM device. */
@@ -134,7 +134,7 @@ class AT24Cxx {
134134
return;
135135
}
136136

137-
FUNC_PREFIX(I2cSetAddress(m_nSlaveAddress));
137+
FUNC_PREFIX(I2cSetAddress(m_device_address));
138138

139139
while (!AckRead())
140140
;
@@ -151,7 +151,7 @@ class AT24Cxx {
151151
{ static_cast<char>(nMemoryAddress & 0xFF),
152152
static_cast<char>(nData)
153153
};
154-
FUNC_PREFIX(I2cSetAddress(m_nSlaveAddress | ((nMemoryAddress >> 8) & 0x7)));
154+
FUNC_PREFIX(I2cSetAddress(m_device_address | ((nMemoryAddress >> 8) & 0x7)));
155155
FUNC_PREFIX(I2cWrite(buffer, (sizeof(buffer) / sizeof(buffer[0]))));
156156
}
157157
}
@@ -171,7 +171,7 @@ class AT24Cxx {
171171
char buffer[128];
172172
uint32_t nIndex = 0;
173173

174-
FUNC_PREFIX(I2cSetAddress(m_nSlaveAddress));
174+
FUNC_PREFIX(I2cSetAddress(m_device_address));
175175

176176
while (nLength > 0) {
177177
while (!AckRead());
@@ -191,7 +191,7 @@ class AT24Cxx {
191191
buffer[0] = static_cast<char>(nMemoryAddress & 0xFF);
192192
memcpy(&buffer[1], &pData[nIndex], nCount);
193193

194-
FUNC_PREFIX(I2cSetAddress(m_nSlaveAddress | ((nMemoryAddress >> 8) & 0x7)));
194+
FUNC_PREFIX(I2cSetAddress(m_device_address | ((nMemoryAddress >> 8) & 0x7)));
195195
FUNC_PREFIX(I2cWrite(buffer, 1 + nCount));
196196
}
197197

@@ -212,7 +212,7 @@ class AT24Cxx {
212212
return 0;
213213
}
214214

215-
FUNC_PREFIX(I2cSetAddress(m_nSlaveAddress));
215+
FUNC_PREFIX(I2cSetAddress(m_device_address));
216216

217217
while (!AckRead());
218218

@@ -224,7 +224,7 @@ class AT24Cxx {
224224
FUNC_PREFIX(I2cWrite(buffer, sizeof(buffer) / sizeof(buffer[0])));
225225
} else {
226226
const char buffer[] = { static_cast<char>(nMemoryAddress & 0xFF) };
227-
FUNC_PREFIX(I2cSetAddress(m_nSlaveAddress | ((nMemoryAddress >> 8) & 0x7)));
227+
FUNC_PREFIX(I2cSetAddress(m_device_address | ((nMemoryAddress >> 8) & 0x7)));
228228
FUNC_PREFIX(I2cWrite(buffer, sizeof(buffer) / sizeof(buffer[0])));
229229
}
230230

@@ -246,7 +246,7 @@ class AT24Cxx {
246246
return 1;
247247
}
248248

249-
FUNC_PREFIX(I2cSetAddress(m_nSlaveAddress));
249+
FUNC_PREFIX(I2cSetAddress(m_device_address));
250250

251251
while (!AckRead());
252252

@@ -259,7 +259,7 @@ class AT24Cxx {
259259
FUNC_PREFIX(I2cWrite(buffer, sizeof(buffer) / sizeof(buffer[0])));
260260
} else {
261261
const char buffer[] = { static_cast<char>(nMemoryAddress & 0xFF) };
262-
FUNC_PREFIX(I2cSetAddress(m_nSlaveAddress | ((nMemoryAddress >> 8) & 0x7)));
262+
FUNC_PREFIX(I2cSetAddress(m_device_address | ((nMemoryAddress >> 8) & 0x7)));
263263
FUNC_PREFIX(I2cWrite(buffer, sizeof(buffer) / sizeof(buffer[0])));
264264
}
265265

@@ -277,7 +277,7 @@ class AT24Cxx {
277277
static constexpr bool isAddressSizeTwoWords = type > at24cxx::ATTypes::AT24LC16;
278278

279279
private:
280-
uint8_t m_nSlaveAddress;
280+
uint8_t m_device_address;
281281
bool m_IsConnected { false };
282282
};
283283

lib-gd32/include/gd32.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,23 @@ uint16_t bkp_data_read(bkp_data_register_enum register_number);
9595
#define GPIO_OSPEED GPIO_OSPEED_50MHZ
9696
#endif
9797

98-
#define GD32_PORT_TO_GPIO(p, n) ((p * 16) + n)
99-
#define GD32_GPIO_TO_PORT(g) (uint8_t)(g / 16)
100-
#define GD32_GPIO_TO_NUMBER(g) (uint8_t)(g - (16 * GD32_GPIO_TO_PORT(g)))
98+
#ifdef __cplusplus
99+
constexpr uint32_t Gd32PortToGpio(uint32_t port, uint32_t pin) {
100+
return (port * 16U) + pin;
101+
}
102+
103+
constexpr uint8_t Gd32GpioToPort(uint32_t gpio) {
104+
return static_cast<uint8_t>(gpio / 16U);
105+
}
106+
107+
constexpr uint8_t Gd32GpioToNumber(uint32_t gpio) {
108+
return static_cast<uint8_t>(gpio % 16U);
109+
}
110+
111+
#define GD32_PORT_TO_GPIO(p, n) Gd32PortToGpio((p), (n))
112+
#define GD32_GPIO_TO_PORT(g) Gd32GpioToPort((g))
113+
#define GD32_GPIO_TO_NUMBER(g) Gd32GpioToNumber((g))
114+
#endif
101115

102116
typedef enum T_GD32_Port {
103117
GD32_GPIO_PORTA = 0,

lib-gd32/include/gd32_gpio.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,33 +156,31 @@ inline void Gd32GpioIntCfg(uint32_t gpio, uint32_t trig_type) {
156156
#endif
157157

158158
inline uint32_t Gd32GpioToPeriph(uint32_t gpio) {
159-
switch ((GD32_Port_TypeDef)GD32_GPIO_TO_PORT(gpio)) {
159+
const auto kPortIndex = Gd32GpioToPort(gpio);
160+
const auto kPort = static_cast<GD32_Port_TypeDef>(kPortIndex);
161+
162+
switch (kPort) {
160163
case GD32_GPIO_PORTA:
161164
case GD32_GPIO_PORTB:
162165
case GD32_GPIO_PORTC:
163166
case GD32_GPIO_PORTD:
164167
case GD32_GPIO_PORTE:
165168
case GD32_GPIO_PORTF:
166169
case GD32_GPIO_PORTG:
167-
return GPIOA + (GD32_GPIO_TO_PORT(gpio) * 0x400);
168-
break;
170+
return GPIOA + (kPortIndex * 0x400);
169171
#if !(defined(GD32F10X) || defined(GD32F30X))
170172
case GD32_GPIO_PORTH:
171173
return GPIOH;
172-
break;
173174
#if !defined(GD32H7XX)
174175
case GD32_GPIO_PORTI:
175176
return GPIOI;
176-
break;
177177
#endif
178178
#endif
179179
#if defined(GD32H7XX)
180180
case GD32_GPIO_PORTJ:
181181
return GPIOJ;
182-
break;
183182
case GD32_GPIO_PORTK:
184183
return GPIOK;
185-
break;
186184
#endif
187185
default:
188186
assert(false && "Invalid gpio");

lib-gd32/include/gd32_i2c.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ uint8_t Gd32I2cRead(uint8_t address, char* buffer, uint32_t length);
5353
bool Gd32I2cIsConnected(uint8_t address, uint32_t baudrate = gd32::kI2CNormalSpeed);
5454
void Gd32I2cWriteReg(uint8_t reg, uint8_t value);
5555
void Gd32I2cWriteReg(uint8_t address, uint8_t reg, uint8_t value);
56+
void Gd32I2cWriteReg(uint8_t reg, uint16_t value);
57+
void Gd32I2cWriteReg(uint8_t address, uint8_t reg, uint16_t value);
5658
void Gd32I2cReadReg(uint8_t reg, uint8_t& value);
5759
void Gd32I2cReadReg(uint8_t address, uint8_t reg, uint8_t& value);
5860

lib-gd32/include/i2c.h

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/**
2+
* @file i2c.h
3+
*
4+
*/
5+
/* Copyright (C) 2026 by Arjan van Vught mailto:info@gd32-dmx.org
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
26+
#ifndef I2C_H_
27+
#define I2C_H_
28+
29+
#include <cstdint>
30+
31+
#include "gd32_i2c.h"
32+
#include "timing.h"
33+
34+
namespace i2c {
35+
inline constexpr uint32_t kNormalSpeed = gd32::kI2CNormalSpeed;
36+
inline constexpr uint32_t kFullSpeed = gd32::kI2CFullSpeed;
37+
38+
struct ReturnCode {
39+
static constexpr uint8_t kOk = GD32_I2C_OK;
40+
static constexpr uint8_t kNok = GD32_I2C_NOK;
41+
static constexpr uint8_t kNack = GD32_I2C_NACK;
42+
static constexpr uint8_t kNokLa = GD32_I2C_NOK_LA;
43+
static constexpr uint8_t kNokTout = GD32_I2C_NOK_TOUT;
44+
};
45+
46+
inline void Begin() {
47+
Gd32I2cBegin();
48+
}
49+
50+
inline void SetBaudrate(uint32_t baudrate) {
51+
Gd32I2cSetBaudrate(baudrate);
52+
}
53+
54+
inline void SetAddress(uint8_t address) {
55+
Gd32I2cSetAddress(address);
56+
}
57+
58+
inline uint8_t Write(const char* buffer, uint32_t length) {
59+
return Gd32I2cWrite(buffer, length);
60+
}
61+
62+
inline uint8_t Write(uint8_t address, const char* buffer, uint32_t length) {
63+
return Gd32I2cWrite(address, buffer, length);
64+
}
65+
66+
inline void Write(uint8_t data) {
67+
const char kBuffer[] = {static_cast<char>(data)};
68+
Write(kBuffer, 1);
69+
}
70+
71+
inline uint8_t Read(char* buffer, uint32_t length) {
72+
return Gd32I2cRead(buffer, length);
73+
}
74+
75+
inline uint8_t Read(uint8_t address, char* buffer, uint32_t length) {
76+
return Gd32I2cRead(address, buffer, length);
77+
}
78+
79+
inline uint16_t Read16() {
80+
char buf[2] = {0};
81+
Read(buf, 2);
82+
return static_cast<uint16_t>(static_cast<uint16_t>(buf[0]) << 8 | static_cast<uint16_t>(buf[1]));
83+
}
84+
85+
inline bool IsConnected(uint8_t address, uint32_t baudrate = kNormalSpeed) {
86+
return Gd32I2cIsConnected(address, baudrate);
87+
}
88+
89+
inline void WriteReg(uint8_t reg, uint8_t value) {
90+
Gd32I2cWriteReg(reg, value);
91+
}
92+
93+
inline void WriteReg(uint8_t reg, uint16_t value) {
94+
Gd32I2cWriteReg(reg, value);
95+
}
96+
97+
inline void WriteReg(uint8_t address, uint8_t reg, uint8_t value) {
98+
Gd32I2cWriteReg(address, reg, value);
99+
}
100+
101+
inline void ReadReg(uint8_t reg, uint8_t& value) {
102+
Gd32I2cReadReg(reg, value);
103+
}
104+
105+
inline void ReadReg(uint8_t address, uint8_t reg, uint8_t& value) {
106+
Gd32I2cReadReg(address, reg, value);
107+
}
108+
109+
inline uint16_t ReadRegister16(uint8_t reg) {
110+
const char kBuffer[] = {static_cast<char>(reg)};
111+
i2c::Write(&kBuffer[0], 1);
112+
return Read16();
113+
}
114+
115+
inline uint16_t ReadRegister16DelayUs(uint8_t reg, uint32_t delay_us) {
116+
const char kBuffer[] = {static_cast<char>(reg)};
117+
i2c::Write(&kBuffer[0], 1);
118+
timing::DelayUs(delay_us);
119+
return Read16();
120+
}
121+
} // namespace i2c
122+
123+
#endif // I2C_H_

0 commit comments

Comments
 (0)