Quickstart¶
Show text on an ISF15ACP4 from your MCU: wire seven signals and two supplies, write a small port class, call four driver functions.
The 15 V drive supply comes last
Switch VCC (14 V to 16 V) with a GPIO-controlled supply or charge pump that is off at power-up. The datasheet turns it on only after VDD is up and the reset pulse is done, and off before VDD. A VCC that is always on skips that sequence.
1. Wire it¶
| MCU | ISF15ACP4 pin | Notes |
|---|---|---|
| SPI MOSI | 8 SDI | Write only: the display has no data output |
| SPI SCK | 7 SCK | SPI mode 0, up to 6.6 MHz; start at 1 MHz |
| GPIO out | 4 SS | Chip select, active low; the port drives it |
| GPIO out | 6 D/C | Low: command bytes; high: pixel data |
| GPIO out | 5 RES | Reset, active low |
| GPIO out | VCC supply enable | Turns on the 15 V supply that feeds pin 9 |
| GPIO in, pull-up | 1 SW | Pin 2 SW to GND: pressed reads low |
| 2.8 V or 3.3 V | 3 VDD | 2.4 V to 3.5 V; MCU I/O at the same level |
| GND | 10 GND | Common ground for both supplies |
The Hardware page has the timing, the power sequence and the electrical limits.
2. Add the driver¶
Add the repository as a submodule and link the hf_isf15acp4 CMake target (or include inc/ and compile
src/isf15acp4_font_data.cpp with C++20). Installation covers CMake and ESP-IDF.
3. Write the port¶
The port is the only platform code. It writes SPI bytes inside an SS-low transaction with D/C set, drives the
control pins and waits. Replace the platform_* calls with your SDK's.
class MySpi : public isf15acp4::SpiInterface<MySpi> {
public:
// Your board's GPIO numbers.
static constexpr int kCs = 10, kDc = 13, kRes = 14, kVccEn = 9, kSwitch = 8;
bool EnsureInitialized() noexcept {
platform_gpio_write(kCs, true); // SS idle high
platform_gpio_write(kVccEn, false); // 15 V drive supply off until after reset
return platform_spi_init();
}
// D/C low = command, high = data; SS low for the whole transaction.
bool BeginCommand() noexcept { return begin(false); }
bool BeginData() noexcept { return begin(true); }
void EndTransaction() noexcept { platform_gpio_write(kCs, true); }
// Must not return before the last bit is on the wire: SS rises right after.
bool WriteBytes(const uint8_t* data, std::size_t len) noexcept {
return platform_spi_write(data, len);
}
void GpioSet(isf15acp4::CtrlPin pin, isf15acp4::GpioSignal signal) noexcept {
const bool active = signal == isf15acp4::GpioSignal::Active;
switch (pin) {
case isf15acp4::CtrlPin::ChipSelect: platform_gpio_write(kCs, !active); break; // SS active low
case isf15acp4::CtrlPin::DataCommand: platform_gpio_write(kDc, active); break; // high = data
case isf15acp4::CtrlPin::Reset: platform_gpio_write(kRes, !active); break; // RES# active low
case isf15acp4::CtrlPin::VccEnable: platform_gpio_write(kVccEn, active); break;
case isf15acp4::CtrlPin::Switch: break; // input only
}
}
// The switch closes pins 1-2; wired to GND with a pull-up, pressed reads low.
bool GpioRead(isf15acp4::CtrlPin pin) noexcept {
return pin == isf15acp4::CtrlPin::Switch && !platform_gpio_read(kSwitch);
}
void DelayUs(uint32_t us) noexcept { platform_delay_us(us); }
private:
bool begin(bool data) noexcept {
platform_gpio_write(kDc, data);
platform_gpio_write(kCs, false);
return true;
}
};
CtrlPin::Reset is active low like SS: Active holds the controller in reset, Inactive lets it run.
Porting explains each method and the pin levels.
4. Show something¶
#include "isf15acp4.hpp"
int show_ready(MySpi& spi) {
isf15acp4::SmartDisplay<MySpi> display(&spi); // ISF15ACP4, software canvas
if (!display.Initialize()) { // 1. reset, 15 V on, SSD1331 init table
return -1; // wiring, VCC or SPI: see GetLastError()
}
auto gfx = display.CreateGraphicsContext(); // 2. draw into a 96 x 64 RGB565 frame
gfx.Clear(isf15acp4::colors::Black);
gfx.DrawString(4, 4, "READY", isf15acp4::colors::Green);
gfx.DrawRect({0, 0, 95, 63}, isf15acp4::colors::White);
if (!display.Present(gfx)) { // 3. send the frame (12,288 bytes)
return -2;
}
return display.IsPressed() ? 1 : 0; // 4. the switch, through your port
}
What each step does:
Initialize()calls yourEnsureInitialized(), pulses RES for at least 3 µs, enables VCC, waits 1 ms, sends the ISF15ACP4 initialisation table (which ends with display on) and sets the full 96 x 64 window. Nothing else works until it returnstrue.CreateGraphicsContext()returns a canvas the size of the panel. Drawing only changes RAM on your MCU.Present()streams the frame to the display: 12,288 bytes with D/C high.IsPressed()calls yourGpioRead(CtrlPin::Switch).
This example is built by the host CI, so it compiles against the current headers.
If it does not work¶
| Symptom | First thing to check |
|---|---|
Initialize() returns false |
GetLastError(): your EnsureInitialized() or WriteBytes() failed |
Returns true, screen stays dark |
RES ends low (Reset mapping inverted), VCC not at 14 V to 16 V, SS or D/C swapped |
| Shapes in the right place, colours wrong | A leftover byte swap or raw WritePixels() bytes (Troubleshooting) |
| Switch always pressed or never | Pull-up on the SW pin, active level in GpioRead() |