touch with abtraction working, SD is not working
This commit is contained in:
201
basic1 copy.cpp
Normal file
201
basic1 copy.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 4.0" TFT ST7796 with Touch Screen and SD Card Demo - DIRECT DRIVER TEST
|
||||
*/
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "board_config.h" // Board-specific pin configuration
|
||||
#include "sd_card.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "display/low_level_render.h"
|
||||
#include "display/low_level_gui.h"
|
||||
#include "display/low_level_display.h"
|
||||
#include "lib/ft6336u/ft6336u.h" // Direct driver instead of abstraction
|
||||
|
||||
|
||||
// Binary info for RP2350 - ensures proper boot image structure
|
||||
bi_decl(bi_program_description("4.0\" TFT ST7796 with Touch and SD Card Demo"));
|
||||
bi_decl(bi_program_version_string("0.1"));
|
||||
bi_decl(bi_program_build_date_string(__DATE__));
|
||||
|
||||
// Screen dimensions and configuration from board_config.h
|
||||
const int V_WIDTH = DISPLAY_WIDTH;
|
||||
const int V_HEIGHT = DISPLAY_HEIGHT;
|
||||
|
||||
// Touch indicator settings
|
||||
#define TOUCH_RADIUS 10
|
||||
|
||||
uint8_t bit_buffer[V_WIDTH * V_HEIGHT / 8];
|
||||
|
||||
/**
|
||||
* @brief Refresh the screen with the 1-bit buffer
|
||||
*
|
||||
* Displays work directly with 1-bit monochrome buffers.
|
||||
* The display driver internally converts to its native format (RGB565, etc.)
|
||||
*
|
||||
* @param buffer Pointer to 1-bit framebuffer (width*height/8 bytes)
|
||||
* @param display Pointer to display abstraction layer
|
||||
*/
|
||||
void refresh_screen(const uint8_t *buffer, LowLevelDisplay* display) {
|
||||
display->draw_buffer(buffer);
|
||||
display->refresh();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialize standard I/O for debugging with timeout
|
||||
// This prevents hanging when USB is not connected
|
||||
stdio_init_all();
|
||||
sleep_ms(5000); // Wait for USB connection (if present)
|
||||
|
||||
printf("\n=== %s Demo ===\n", BOARD_NAME);
|
||||
|
||||
// Create display abstraction using factory method
|
||||
// The factory handles all board-specific configuration internally
|
||||
LowLevelDisplay* display = LowLevelDisplay::create((DisplayType)DISPLAY_TYPE_SELECTED, V_WIDTH, V_HEIGHT);
|
||||
|
||||
if (!display) {
|
||||
printf("Failed to create display!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Initializing 4.0\" TFT with Touch and SD Card...\n");
|
||||
|
||||
// Initialize the display
|
||||
if (!display->init()) {
|
||||
printf("Display initialization failed!\n");
|
||||
delete display;
|
||||
return -1;
|
||||
}
|
||||
|
||||
display->clear(false); // Clear to black
|
||||
|
||||
LowLevelRenderer renderer(bit_buffer, V_WIDTH, V_HEIGHT);
|
||||
renderer.set_font(&font_5x5_obj);
|
||||
LowLevelGUI gui = LowLevelGUI(&renderer, font_BMplain_obj);
|
||||
LowLevelWindow *w1 = gui.draw_new_window(15, 15, V_WIDTH - 30, V_HEIGHT - 30, "Main Window");
|
||||
gui.draw_status_bar(w1, 10, 40, 200,
|
||||
"PANELS", "Weekly Average Charge", 65, "190KWH");
|
||||
gui.draw_circular_gauge(w1, 10, 100 - 10, 200, "SYSTEM EFF.", 68);
|
||||
|
||||
// Refresh the screen with the rendered GUI
|
||||
refresh_screen(bit_buffer, display);
|
||||
|
||||
// Initialize touch screen using DIRECT DRIVER (bypassing abstraction)
|
||||
printf("\n=== Direct FT6336U Touch Driver Test ===\n");
|
||||
|
||||
ft6336u_config_t touch_config = {
|
||||
.i2c = i2c1,
|
||||
.gpio_sda = 2,
|
||||
.gpio_scl = 3,
|
||||
.gpio_rst = 28,
|
||||
.gpio_int = 25,
|
||||
.screen_width = V_WIDTH,
|
||||
.screen_height = V_HEIGHT,
|
||||
.swap_xy = true,
|
||||
.invert_x = true,
|
||||
.invert_y = false
|
||||
};
|
||||
|
||||
printf("Touch Config:\n");
|
||||
printf(" I2C: i2c1, SDA: 2, SCL: 3\n");
|
||||
printf(" RST: 28, INT: 25\n");
|
||||
printf(" Screen: %dx%d\n", V_WIDTH, V_HEIGHT);
|
||||
printf(" Transforms: swap_xy=%d, invert_x=%d, invert_y=%d\n\n",
|
||||
touch_config.swap_xy, touch_config.invert_x, touch_config.invert_y);
|
||||
fflush(stdout);
|
||||
|
||||
bool touch_ok = ft6336u_init(&touch_config);
|
||||
if (touch_ok) {
|
||||
printf("Touch initialized successfully!\n");
|
||||
printf("Chip ID: 0x%02X, FW Version: 0x%02X\n\n",
|
||||
ft6336u_get_chip_id(), ft6336u_get_firmware_version());
|
||||
|
||||
// Run communication test
|
||||
printf("Running I2C communication test...\n");
|
||||
ft6336u_test_i2c();
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Touch initialization FAILED!\n\n");
|
||||
}
|
||||
|
||||
// Test SD card and FatFS
|
||||
if (sd_card_init_with_board_config()) {
|
||||
sd_card_test_fatfs();
|
||||
} else {
|
||||
printf("SD Card initialization failed or no card present\n");
|
||||
}
|
||||
|
||||
printf("\n=== Entering Touch Test Loop ===\n");
|
||||
printf("Touch the screen to see coordinates...\n\n");
|
||||
fflush(stdout);
|
||||
|
||||
// Main loop - handle touch events with direct driver
|
||||
int last_x = -1, last_y = -1;
|
||||
|
||||
// Touch debouncing
|
||||
uint32_t last_touch_time = 0;
|
||||
const uint32_t debounce_ms = 20;
|
||||
bool was_touched = false;
|
||||
int touch_fail_count = 0;
|
||||
int touch_success_count = 0;
|
||||
|
||||
while (1) {
|
||||
uint32_t now = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
if (now - last_touch_time < debounce_ms) {
|
||||
sleep_ms(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_touched = touch_ok && ft6336u_is_touched();
|
||||
|
||||
if (is_touched) {
|
||||
ft6336u_touch_data_t touch_data;
|
||||
|
||||
if (ft6336u_read_touch(&touch_data)) {
|
||||
touch_success_count++;
|
||||
|
||||
if (touch_data.touch_count > 0) {
|
||||
int16_t x = touch_data.points[0].x;
|
||||
int16_t y = touch_data.points[0].y;
|
||||
|
||||
printf("Touch: X=%d, Y=%d, Event=%d [Success: %d, Fail: %d]\n",
|
||||
x, y, touch_data.points[0].event,
|
||||
touch_success_count, touch_fail_count);
|
||||
fflush(stdout);
|
||||
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
was_touched = true;
|
||||
last_touch_time = now;
|
||||
}
|
||||
} else {
|
||||
touch_fail_count++;
|
||||
if (touch_fail_count % 10 == 0) {
|
||||
printf("Touch read failed (count: %d)\n", touch_fail_count);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (was_touched) {
|
||||
last_x = -1;
|
||||
last_y = -1;
|
||||
was_touched = false;
|
||||
}
|
||||
}
|
||||
|
||||
sleep_ms(5);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
69
basic1.cpp
69
basic1.cpp
@@ -98,9 +98,10 @@ int main()
|
||||
printf("Touch initialized successfully\n");
|
||||
|
||||
// Run communication test if available
|
||||
// Note: Commented out as it may hang on some hardware configurations
|
||||
printf("\nRunning touch reliability test...\n");
|
||||
touch->test_communication();
|
||||
printf("\n");
|
||||
printf("...\n");
|
||||
} else {
|
||||
printf("Touch initialization failed or not configured\n");
|
||||
}
|
||||
@@ -117,7 +118,7 @@ int main()
|
||||
|
||||
// Touch debouncing
|
||||
uint32_t last_touch_time = 0;
|
||||
const uint32_t debounce_ms = 20; // Minimum time between touch reads
|
||||
const uint32_t debounce_ms = 10; // Poll touch every 10ms (100 times per second)
|
||||
bool was_touched = false;
|
||||
int touch_fail_count = 0;
|
||||
int touch_success_count = 0;
|
||||
@@ -125,45 +126,48 @@ int main()
|
||||
printf("Entering main touch loop...\n");
|
||||
|
||||
while (1) {
|
||||
// Always sleep to prevent tight loop and allow other operations
|
||||
sleep_us(100);
|
||||
|
||||
// Check INT pin directly (LOW = touch detected, no I2C transaction needed!)
|
||||
// Much faster than I2C read and doesn't interfere with other operations
|
||||
bool int_pin_low = !gpio_get(TOUCH_INT_PIN);
|
||||
|
||||
// Only process if INT pin indicates touch data available
|
||||
if (int_pin_low) {
|
||||
uint32_t now = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
// Check if enough time has passed since last touch check
|
||||
// Check if enough time has passed since last touch check (debounce)
|
||||
if (now - last_touch_time < debounce_ms) {
|
||||
sleep_ms(1);
|
||||
//continue;
|
||||
}
|
||||
// Now read full touch data via I2C
|
||||
TouchData touch_data;
|
||||
if (!touch->read_touch(&touch_data) || touch_data.touch_count == 0) {
|
||||
// Read failed or no actual touch data
|
||||
touch_fail_count++;
|
||||
was_touched = false;
|
||||
last_x = -1;
|
||||
last_y = -1;
|
||||
last_touch_time = now;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_touched = touch && touch->is_touched();
|
||||
|
||||
// Only process touch if state changed or still touching
|
||||
if (is_touched) {
|
||||
TouchData touch_data;
|
||||
|
||||
if (touch->read_touch(&touch_data)) {
|
||||
touch_success_count++;
|
||||
|
||||
if (touch_data.touch_count > 0) {
|
||||
int16_t x = touch_data.points[0].x;
|
||||
int16_t y = touch_data.points[0].y;
|
||||
uint8_t event = touch_data.points[0].event;
|
||||
uint8_t id = touch_data.points[0].id;
|
||||
uint8_t weight = touch_data.points[0].pressure;
|
||||
uint8_t gesture = touch_data.gesture;
|
||||
|
||||
// Only print occasionally to avoid flooding serial
|
||||
//if (touch_success_count % 5 == 0) {
|
||||
printf("Touch: X=%d, Y=%d, Event=%d [Success: %d, Fail: %d]\n",
|
||||
x, y, touch_data.points[0].event,
|
||||
printf("Touch: X=%d Y=%d Event=%d ID=%d Weight=%d Gesture=0x%02X [S:%d F:%d]\n",
|
||||
x, y, event, id, weight, gesture,
|
||||
touch_success_count, touch_fail_count);
|
||||
//}
|
||||
|
||||
|
||||
// Check if touch is in title area to clear screen
|
||||
if (y < 30) {
|
||||
if (!was_touched) { // Only on new touch
|
||||
// Clear drawing area in bit buffer
|
||||
renderer.draw_filled_rectangle(11, 130, V_WIDTH - 11 - 11, V_HEIGHT - 11 - 130, false, 1);
|
||||
refresh_screen(bit_buffer, display);
|
||||
printf("Drawing area cleared\n");
|
||||
}
|
||||
}
|
||||
// Draw in touch area (white line)
|
||||
else if (y > 100) {
|
||||
|
||||
// Draw line from last position (for smooth drawing)
|
||||
if (last_x >= 0 && last_y >= 0) {
|
||||
@@ -178,18 +182,9 @@ int main()
|
||||
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
}
|
||||
|
||||
was_touched = true;
|
||||
last_touch_time = now;
|
||||
}
|
||||
} else {
|
||||
// Touch detected but read failed
|
||||
touch_fail_count++;
|
||||
if (touch_fail_count % 10 == 0) {
|
||||
printf("Touch read failed (count: %d)\n", touch_fail_count);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Reset last position when not touching
|
||||
if (was_touched) {
|
||||
@@ -198,8 +193,6 @@ int main()
|
||||
was_touched = false;
|
||||
}
|
||||
}
|
||||
|
||||
sleep_ms(5); // Faster polling for better responsiveness
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Binary file not shown.
BIN
basic1_pico2.uf2
BIN
basic1_pico2.uf2
Binary file not shown.
Binary file not shown.
@@ -24,27 +24,30 @@
|
||||
#define TOUCH_INVERT_X true
|
||||
#define TOUCH_INVERT_Y false
|
||||
|
||||
// SPI pins for display
|
||||
// SPI pins for display - Feather RP2350 with 4.0" TFT
|
||||
#define DISPLAY_SPI_PORT spi1
|
||||
#define DISPLAY_SCK_PIN 18
|
||||
#define DISPLAY_MOSI_PIN 19
|
||||
#define DISPLAY_MISO_PIN 20
|
||||
#define DISPLAY_CS_PIN 17
|
||||
#define DISPLAY_DC_PIN 16
|
||||
#define DISPLAY_RST_PIN 15
|
||||
#define DISPLAY_BL_PIN 14
|
||||
#define DISPLAY_SCK_PIN 10 // D10 (SCK)
|
||||
#define DISPLAY_MOSI_PIN 11 // D11 (MOSI)
|
||||
#define DISPLAY_MISO_PIN 20 // Not used for display
|
||||
#define DISPLAY_CS_PIN 7 // D13 (CS)
|
||||
#define DISPLAY_DC_PIN 4 // D4 (DC)
|
||||
#define DISPLAY_RST_PIN 9 // D9 (RST)
|
||||
#define DISPLAY_BL_PIN 6 // D6 (Backlight)
|
||||
#define DISPLAY_BUSY_PIN 13 // For e-paper displays
|
||||
|
||||
// I2C pins for touch
|
||||
#define TOUCH_I2C_PORT i2c0
|
||||
#define TOUCH_SDA_PIN 4
|
||||
#define TOUCH_SCL_PIN 5
|
||||
#define TOUCH_INT_PIN 6
|
||||
#define TOUCH_RST_PIN 7
|
||||
// I2C pins for touch - Feather I2C default
|
||||
#define TOUCH_I2C_PORT i2c1
|
||||
#define TOUCH_SDA_PIN 2
|
||||
#define TOUCH_SCL_PIN 3
|
||||
#define TOUCH_INT_PIN 25
|
||||
#define TOUCH_RST_PIN 28
|
||||
|
||||
// SD card pins (shared SPI with display)
|
||||
#define SD_SPI_PORT spi1
|
||||
#define SD_CS_PIN 10
|
||||
#define SD_CS_PIN 5
|
||||
#define SD_MISO_PIN 24
|
||||
#define SD_MOSI_PIN 11
|
||||
#define SD_SCK_PIN 10
|
||||
|
||||
#elif defined(PICO_BOARD) && (PICO_BOARD == pico2 || PICO_BOARD == pico2_w)
|
||||
// Raspberry Pi Pico 2 / Pico 2 W pinout
|
||||
|
||||
@@ -8,16 +8,30 @@ set -e # Exit on error
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BUILD_DIR="${PROJECT_DIR}/build"
|
||||
UF2_FILE="${BUILD_DIR}/basic1.uf2"
|
||||
NINJA="${HOME}/.pico-sdk/ninja/v1.12.1/ninja"
|
||||
|
||||
echo "=========================================="
|
||||
echo " Pico RP2350 Build and Flash Script"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Check if build directory exists and has build.ninja
|
||||
if [ ! -f "${BUILD_DIR}/build.ninja" ]; then
|
||||
echo "⚠ Build not configured. Running cmake..."
|
||||
cd "${PROJECT_DIR}"
|
||||
cmake -B build -G Ninja -DPICO_BOARD=adafruit_feather_rp2350
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Step 1: Build the project
|
||||
echo "Step 1: Building project..."
|
||||
cd "${BUILD_DIR}"
|
||||
make -j4
|
||||
|
||||
if [ -f "${NINJA}" ]; then
|
||||
"${NINJA}"
|
||||
else
|
||||
ninja
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Build failed!"
|
||||
@@ -36,75 +50,34 @@ fi
|
||||
echo "UF2 file created: ${UF2_FILE}"
|
||||
echo ""
|
||||
|
||||
# Step 2: Flash to board
|
||||
echo "Step 2: Flashing to board..."
|
||||
# Step 2: Flash to board using picotool
|
||||
echo "Step 2: Flashing to board using picotool..."
|
||||
echo "Make sure your board is connected and in BOOTSEL mode"
|
||||
echo "(Hold BOOTSEL button while plugging in USB)"
|
||||
echo ""
|
||||
echo "Choose flashing method:"
|
||||
echo " 1) Use picotool (board must be connected and in BOOTSEL mode)"
|
||||
echo " 2) Manual copy (mount board as USB drive and copy UF2)"
|
||||
echo ""
|
||||
read -p "Enter choice (1 or 2): " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
echo ""
|
||||
echo "Using picotool to flash..."
|
||||
echo "Make sure your board is connected and in BOOTSEL mode"
|
||||
echo "(Hold BOOTSEL button while plugging in USB)"
|
||||
echo ""
|
||||
read -p "Press Enter when ready..."
|
||||
PICOTOOL="${HOME}/.pico-sdk/picotool/2.2.0-a4/picotool/picotool"
|
||||
|
||||
PICOTOOL="${HOME}/.pico-sdk/picotool/2.2.0-a4/picotool/picotool"
|
||||
|
||||
if [ ! -f "${PICOTOOL}" ]; then
|
||||
if [ ! -f "${PICOTOOL}" ]; then
|
||||
echo "❌ picotool not found at: ${PICOTOOL}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Try to load the UF2
|
||||
"${PICOTOOL}" load "${UF2_FILE}" -fx
|
||||
# Try to load the UF2
|
||||
"${PICOTOOL}" load "${UF2_FILE}" -fx
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
if [ $? -eq 0 ]; then
|
||||
echo ""
|
||||
echo "✓ Successfully flashed to board!"
|
||||
echo "✓ Board will automatically reboot and run the program"
|
||||
else
|
||||
else
|
||||
echo ""
|
||||
echo "❌ Flash failed! Make sure:"
|
||||
echo " - Board is in BOOTSEL mode (hold BOOTSEL while plugging in)"
|
||||
echo " - USB cable is connected"
|
||||
echo " - You have permission to access USB devices"
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
echo ""
|
||||
echo "Manual copy instructions:"
|
||||
echo "1. Hold BOOTSEL button on your board"
|
||||
echo "2. Plug in USB cable (or press RESET while holding BOOTSEL)"
|
||||
echo "3. Board should appear as USB drive (RPI-RP2)"
|
||||
echo "4. Copy this file to the drive:"
|
||||
echo " ${UF2_FILE}"
|
||||
echo "5. Board will automatically reboot when copy completes"
|
||||
echo ""
|
||||
|
||||
# Try to detect if RPI-RP2 drive is mounted
|
||||
if [ -d "/Volumes/RPI-RP2" ]; then
|
||||
echo "✓ Detected RPI-RP2 drive at /Volumes/RPI-RP2"
|
||||
read -p "Copy UF2 file now? (y/n): " copy_now
|
||||
if [ "$copy_now" = "y" ] || [ "$copy_now" = "Y" ]; then
|
||||
cp "${UF2_FILE}" /Volumes/RPI-RP2/
|
||||
echo "✓ File copied! Board will reboot automatically..."
|
||||
fi
|
||||
else
|
||||
echo "⚠ RPI-RP2 drive not detected"
|
||||
echo "Please manually copy the UF2 file when the drive appears"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
|
||||
@@ -36,6 +36,20 @@ bool LowLevelTouchFT6336U::init() {
|
||||
.invert_y = invert_y
|
||||
};
|
||||
|
||||
// Print the complete configuration for debugging
|
||||
printf("\n=== FT6336U Touch Configuration ===\n");
|
||||
printf(" I2C Port: %s\n", config.i2c == i2c0 ? "i2c0" : "i2c1");
|
||||
printf(" SDA Pin: %d\n", config.gpio_sda);
|
||||
printf(" SCL Pin: %d\n", config.gpio_scl);
|
||||
printf(" RST Pin: %d\n", config.gpio_rst);
|
||||
printf(" INT Pin: %d\n", config.gpio_int);
|
||||
printf(" Screen: %dx%d\n", config.screen_width, config.screen_height);
|
||||
printf(" Swap XY: %s\n", config.swap_xy ? "true" : "false");
|
||||
printf(" Invert X: %s\n", config.invert_x ? "true" : "false");
|
||||
printf(" Invert Y: %s\n", config.invert_y ? "true" : "false");
|
||||
printf("===================================\n\n");
|
||||
fflush(stdout);
|
||||
|
||||
initialized = ft6336u_init(&config);
|
||||
|
||||
if (initialized) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static ft6336u_config_t g_config_storage;
|
||||
static const ft6336u_config_t *g_config = NULL;
|
||||
|
||||
// Helper function to write a register
|
||||
@@ -18,29 +19,48 @@ static bool ft6336u_write_reg(uint8_t reg, uint8_t value) {
|
||||
|
||||
// Helper function to read a register
|
||||
static bool ft6336u_read_reg(uint8_t reg, uint8_t *value) {
|
||||
// Retry up to 3 times like Arduino library
|
||||
for (int retry = 0; retry < 3; retry++) {
|
||||
int result = i2c_write_blocking(g_config->i2c, FT6336U_ADDR, ®, 1, true);
|
||||
if (result != 1) {
|
||||
printf("[FT6336U] I2C write failed: result=%d (expected 1)\n", result);
|
||||
if (result == PICO_ERROR_GENERIC) printf(" Error: PICO_ERROR_GENERIC\n");
|
||||
if (result == PICO_ERROR_TIMEOUT) printf(" Error: PICO_ERROR_TIMEOUT\n");
|
||||
return false;
|
||||
sleep_us(1000); // 1ms delay before retry
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add delay after write, before read (like Arduino library does)
|
||||
sleep_us(10000); // 10ms delay
|
||||
|
||||
result = i2c_read_blocking(g_config->i2c, FT6336U_ADDR, value, 1, false);
|
||||
if (result != 1) {
|
||||
printf("[FT6336U] I2C read failed: result=%d (expected 1)\n", result);
|
||||
return false;
|
||||
}
|
||||
if (result == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
sleep_us(1000); // 1ms delay before retry
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper function to read multiple registers
|
||||
static bool ft6336u_read_regs(uint8_t reg, uint8_t *buf, size_t len) {
|
||||
// Retry up to 3 times
|
||||
for (int retry = 0; retry < 3; retry++) {
|
||||
int result = i2c_write_blocking(g_config->i2c, FT6336U_ADDR, ®, 1, true);
|
||||
if (result != 1) return false;
|
||||
if (result != 1) {
|
||||
sleep_us(1000); // 1ms delay before retry
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add delay after write, before read (like Arduino library does)
|
||||
sleep_us(10000); // 10ms delay
|
||||
|
||||
result = i2c_read_blocking(g_config->i2c, FT6336U_ADDR, buf, len, false);
|
||||
return result == (int)len;
|
||||
if (result == (int)len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
sleep_us(1000); // 1ms delay before retry
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ft6336u_init(const ft6336u_config_t *config) {
|
||||
@@ -53,7 +73,9 @@ bool ft6336u_init(const ft6336u_config_t *config) {
|
||||
printf("[FT6336U] Pins: SDA=%d, SCL=%d, RST=%d, INT=%d\n",
|
||||
config->gpio_sda, config->gpio_scl, config->gpio_rst, config->gpio_int);
|
||||
|
||||
g_config = config;
|
||||
// Copy config to static storage to avoid dangling pointer
|
||||
memcpy(&g_config_storage, config, sizeof(ft6336u_config_t));
|
||||
g_config = &g_config_storage;
|
||||
|
||||
// Initialize I2C
|
||||
printf("[FT6336U] Initializing I2C at 400 kHz...\n");
|
||||
@@ -115,6 +137,17 @@ bool ft6336u_init(const ft6336u_config_t *config) {
|
||||
printf("[FT6336U] WARNING: Failed to set device mode\n");
|
||||
}
|
||||
|
||||
// Enable trigger mode for better gesture and interrupt support
|
||||
printf("[FT6336U] Enabling trigger mode...\n");
|
||||
if (!ft6336u_write_reg(FT6336U_REG_G_MODE, FT6336U_G_MODE_TRIGGER)) {
|
||||
printf("[FT6336U] WARNING: Failed to set G_MODE\n");
|
||||
}
|
||||
|
||||
// Verify gesture mode was set
|
||||
uint8_t g_mode = ft6336u_get_g_mode();
|
||||
printf("[FT6336U] G_MODE: 0x%02X (%s mode)\n",
|
||||
g_mode, g_mode == FT6336U_G_MODE_TRIGGER ? "trigger" : "polling");
|
||||
|
||||
printf("[FT6336U] Initialization complete!\n");
|
||||
return true;
|
||||
}
|
||||
@@ -124,27 +157,13 @@ bool ft6336u_read_touch(ft6336u_touch_data_t *data) {
|
||||
|
||||
memset(data, 0, sizeof(ft6336u_touch_data_t));
|
||||
|
||||
// Small delay to ensure touch controller is ready
|
||||
sleep_us(100);
|
||||
|
||||
// Read gesture ID (optional, skip if causing issues)
|
||||
// Read gesture ID
|
||||
ft6336u_read_reg(FT6336U_REG_GESTURE_ID, &data->gesture);
|
||||
|
||||
// Read number of touch points - retry on failure
|
||||
// Read number of touch points (with retries)
|
||||
uint8_t td_status;
|
||||
int retry_count = 3;
|
||||
bool success = false;
|
||||
|
||||
for (int retry = 0; retry < retry_count; retry++) {
|
||||
if (ft6336u_read_reg(FT6336U_REG_TD_STATUS, &td_status)) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
sleep_us(500); // Brief delay before retry
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return false; // Failed after retries
|
||||
if (!ft6336u_read_reg(FT6336U_REG_TD_STATUS, &td_status)) {
|
||||
return false; // I2C error
|
||||
}
|
||||
|
||||
data->touch_count = td_status & 0x0F;
|
||||
@@ -157,22 +176,12 @@ bool ft6336u_read_touch(ft6336u_touch_data_t *data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read touch point data (6 bytes per point)
|
||||
// Read touch point data (6 bytes per point: XH, XL, YH, YL, WEIGHT, MISC)
|
||||
for (int i = 0; i < data->touch_count; i++) {
|
||||
uint8_t reg_base = (i == 0) ? FT6336U_REG_P1_XH : FT6336U_REG_P2_XH;
|
||||
uint8_t buf[6];
|
||||
|
||||
// Retry read if it fails
|
||||
bool read_success = false;
|
||||
for (int retry = 0; retry < 3; retry++) {
|
||||
if (ft6336u_read_regs(reg_base, buf, 6)) {
|
||||
read_success = true;
|
||||
break;
|
||||
}
|
||||
sleep_us(200);
|
||||
}
|
||||
|
||||
if (!read_success) {
|
||||
if (!ft6336u_read_regs(reg_base, buf, 6)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -181,7 +190,8 @@ bool ft6336u_read_touch(ft6336u_touch_data_t *data) {
|
||||
uint16_t raw_x = ((buf[0] & 0x0F) << 8) | buf[1];
|
||||
uint16_t raw_y = ((buf[2] & 0x0F) << 8) | buf[3];
|
||||
data->points[i].id = (buf[2] >> 4) & 0x0F;
|
||||
data->points[i].weight = buf[4];
|
||||
data->points[i].weight = buf[4]; // Touch pressure/area
|
||||
data->points[i].misc = (buf[5] >> 4) & 0x0F; // Touch area (upper nibble)
|
||||
|
||||
// Apply coordinate transformations
|
||||
if (g_config->swap_xy) {
|
||||
@@ -294,3 +304,28 @@ bool ft6336u_test_i2c(void) {
|
||||
|
||||
return overall;
|
||||
}
|
||||
|
||||
bool ft6336u_set_g_mode(uint8_t mode) {
|
||||
if (g_config == NULL) return false;
|
||||
return ft6336u_write_reg(FT6336U_REG_G_MODE, mode);
|
||||
}
|
||||
|
||||
uint8_t ft6336u_get_g_mode(void) {
|
||||
if (g_config == NULL) return 0xFF;
|
||||
|
||||
uint8_t g_mode;
|
||||
if (!ft6336u_read_reg(FT6336U_REG_G_MODE, &g_mode)) {
|
||||
return 0xFF;
|
||||
}
|
||||
return g_mode;
|
||||
}
|
||||
|
||||
uint8_t ft6336u_get_power_mode(void) {
|
||||
if (g_config == NULL) return 0xFF;
|
||||
|
||||
uint8_t pwr_mode;
|
||||
if (!ft6336u_read_reg(FT6336U_REG_POWER_MODE, &pwr_mode)) {
|
||||
return 0xFF;
|
||||
}
|
||||
return pwr_mode;
|
||||
}
|
||||
|
||||
296
lib/ft6336u/ft6336u.c.bak
Normal file
296
lib/ft6336u/ft6336u.c.bak
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* FT6336U Capacitive Touch Screen Driver Implementation
|
||||
*/
|
||||
|
||||
#include "ft6336u.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static const ft6336u_config_t *g_config = NULL;
|
||||
|
||||
// Helper function to write a register
|
||||
static bool ft6336u_write_reg(uint8_t reg, uint8_t value) {
|
||||
uint8_t buf[2] = {reg, value};
|
||||
int result = i2c_write_blocking(g_config->i2c, FT6336U_ADDR, buf, 2, false);
|
||||
return result == 2;
|
||||
}
|
||||
|
||||
// Helper function to read a register
|
||||
static bool ft6336u_read_reg(uint8_t reg, uint8_t *value) {
|
||||
int result = i2c_write_blocking(g_config->i2c, FT6336U_ADDR, ®, 1, true);
|
||||
if (result != 1) {
|
||||
printf("[FT6336U] I2C write failed: result=%d (expected 1)\n", result);
|
||||
if (result == PICO_ERROR_GENERIC) printf(" Error: PICO_ERROR_GENERIC\n");
|
||||
if (result == PICO_ERROR_TIMEOUT) printf(" Error: PICO_ERROR_TIMEOUT\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
result = i2c_read_blocking(g_config->i2c, FT6336U_ADDR, value, 1, false);
|
||||
if (result != 1) {
|
||||
printf("[FT6336U] I2C read failed: result=%d (expected 1)\n", result);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function to read multiple registers
|
||||
static bool ft6336u_read_regs(uint8_t reg, uint8_t *buf, size_t len) {
|
||||
int result = i2c_write_blocking(g_config->i2c, FT6336U_ADDR, ®, 1, true);
|
||||
if (result != 1) return false;
|
||||
|
||||
result = i2c_read_blocking(g_config->i2c, FT6336U_ADDR, buf, len, false);
|
||||
return result == (int)len;
|
||||
}
|
||||
|
||||
bool ft6336u_init(const ft6336u_config_t *config) {
|
||||
if (config == NULL) {
|
||||
printf("[FT6336U] ERROR: config is NULL\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("[FT6336U] Initializing touch controller...\n");
|
||||
printf("[FT6336U] Pins: SDA=%d, SCL=%d, RST=%d, INT=%d\n",
|
||||
config->gpio_sda, config->gpio_scl, config->gpio_rst, config->gpio_int);
|
||||
|
||||
g_config = config;
|
||||
|
||||
// Initialize I2C
|
||||
printf("[FT6336U] Initializing I2C at 400 kHz...\n");
|
||||
uint actual_freq = i2c_init(config->i2c, 400000); // 400 kHz
|
||||
printf("[FT6336U] I2C actual frequency: %u Hz\n", actual_freq);
|
||||
|
||||
gpio_set_function(config->gpio_sda, GPIO_FUNC_I2C);
|
||||
gpio_set_function(config->gpio_scl, GPIO_FUNC_I2C);
|
||||
gpio_pull_up(config->gpio_sda);
|
||||
gpio_pull_up(config->gpio_scl);
|
||||
printf("[FT6336U] I2C pins configured\n");
|
||||
|
||||
// Initialize reset pin
|
||||
gpio_init(config->gpio_rst);
|
||||
gpio_set_dir(config->gpio_rst, GPIO_OUT);
|
||||
printf("[FT6336U] Reset pin configured\n");
|
||||
|
||||
// Initialize interrupt pin (input with pull-up)
|
||||
gpio_init(config->gpio_int);
|
||||
gpio_set_dir(config->gpio_int, GPIO_IN);
|
||||
gpio_pull_up(config->gpio_int);
|
||||
printf("[FT6336U] Interrupt pin configured\n");
|
||||
|
||||
// Reset the touch controller
|
||||
printf("[FT6336U] Resetting touch controller...\n");
|
||||
gpio_put(config->gpio_rst, 0);
|
||||
sleep_ms(10);
|
||||
gpio_put(config->gpio_rst, 1);
|
||||
sleep_ms(300); // Wait for chip to initialize
|
||||
printf("[FT6336U] Reset complete, reading chip ID...\n");
|
||||
|
||||
// Verify chip ID
|
||||
uint8_t chip_id = ft6336u_get_chip_id();
|
||||
printf("[FT6336U] Chip ID read attempt 1: 0x%02X (expected 0x64)\n", chip_id);
|
||||
|
||||
if (chip_id != 0x64) {
|
||||
// Try again - sometimes first read fails
|
||||
printf("[FT6336U] First read failed, retrying...\n");
|
||||
sleep_ms(100);
|
||||
chip_id = ft6336u_get_chip_id();
|
||||
printf("[FT6336U] Chip ID read attempt 2: 0x%02X\n", chip_id);
|
||||
|
||||
if (chip_id != 0x64) {
|
||||
printf("[FT6336U] ERROR: Invalid chip ID! Check I2C wiring and address.\n");
|
||||
printf("[FT6336U] Possible issues:\n");
|
||||
printf(" - I2C pins not connected properly\n");
|
||||
printf(" - Touch controller not powered\n");
|
||||
printf(" - Wrong I2C address (using 0x%02X)\n", FT6336U_ADDR);
|
||||
printf(" - I2C pull-up resistors missing\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
printf("[FT6336U] Chip ID verified successfully!\n");
|
||||
|
||||
// Set to normal operating mode
|
||||
printf("[FT6336U] Setting normal operating mode...\n");
|
||||
if (!ft6336u_write_reg(FT6336U_REG_DEVICE_MODE, 0x00)) {
|
||||
printf("[FT6336U] WARNING: Failed to set device mode\n");
|
||||
}
|
||||
|
||||
printf("[FT6336U] Initialization complete!\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ft6336u_read_touch(ft6336u_touch_data_t *data) {
|
||||
if (data == NULL || g_config == NULL) return false;
|
||||
|
||||
memset(data, 0, sizeof(ft6336u_touch_data_t));
|
||||
|
||||
// Small delay to ensure touch controller is ready
|
||||
sleep_us(100);
|
||||
|
||||
// Read gesture ID (optional, skip if causing issues)
|
||||
ft6336u_read_reg(FT6336U_REG_GESTURE_ID, &data->gesture);
|
||||
|
||||
// Read number of touch points - retry on failure
|
||||
uint8_t td_status;
|
||||
int retry_count = 3;
|
||||
bool success = false;
|
||||
|
||||
for (int retry = 0; retry < retry_count; retry++) {
|
||||
if (ft6336u_read_reg(FT6336U_REG_TD_STATUS, &td_status)) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
sleep_us(500); // Brief delay before retry
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return false; // Failed after retries
|
||||
}
|
||||
|
||||
data->touch_count = td_status & 0x0F;
|
||||
if (data->touch_count > FT6336U_MAX_TOUCH_POINTS) {
|
||||
data->touch_count = FT6336U_MAX_TOUCH_POINTS;
|
||||
}
|
||||
|
||||
// If no touches, return early
|
||||
if (data->touch_count == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read touch point data (6 bytes per point)
|
||||
for (int i = 0; i < data->touch_count; i++) {
|
||||
uint8_t reg_base = (i == 0) ? FT6336U_REG_P1_XH : FT6336U_REG_P2_XH;
|
||||
uint8_t buf[6];
|
||||
|
||||
// Retry read if it fails
|
||||
bool read_success = false;
|
||||
for (int retry = 0; retry < 3; retry++) {
|
||||
if (ft6336u_read_regs(reg_base, buf, 6)) {
|
||||
read_success = true;
|
||||
break;
|
||||
}
|
||||
sleep_us(200);
|
||||
}
|
||||
|
||||
if (!read_success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse touch point data
|
||||
data->points[i].event = (buf[0] >> 6) & 0x03;
|
||||
uint16_t raw_x = ((buf[0] & 0x0F) << 8) | buf[1];
|
||||
uint16_t raw_y = ((buf[2] & 0x0F) << 8) | buf[3];
|
||||
data->points[i].id = (buf[2] >> 4) & 0x0F;
|
||||
data->points[i].weight = buf[4];
|
||||
|
||||
// Apply coordinate transformations
|
||||
if (g_config->swap_xy) {
|
||||
uint16_t temp = raw_x;
|
||||
raw_x = raw_y;
|
||||
raw_y = temp;
|
||||
}
|
||||
|
||||
if (g_config->invert_x) {
|
||||
raw_x = g_config->screen_width - 1 - raw_x;
|
||||
}
|
||||
|
||||
if (g_config->invert_y) {
|
||||
raw_y = g_config->screen_height - 1 - raw_y;
|
||||
}
|
||||
|
||||
data->points[i].x = raw_x;
|
||||
data->points[i].y = raw_y;
|
||||
|
||||
// Ensure coordinates are within screen bounds
|
||||
if (data->points[i].x >= g_config->screen_width) {
|
||||
data->points[i].x = g_config->screen_width - 1;
|
||||
}
|
||||
if (data->points[i].y >= g_config->screen_height) {
|
||||
data->points[i].y = g_config->screen_height - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ft6336u_is_touched(void) {
|
||||
if (g_config == NULL) return false;
|
||||
|
||||
// More reliable: Read TD_STATUS register directly
|
||||
// INT pin can be unreliable due to timing/noise
|
||||
uint8_t td_status;
|
||||
if (!ft6336u_read_reg(FT6336U_REG_TD_STATUS, &td_status)) {
|
||||
return false; // I2C error, assume not touched
|
||||
}
|
||||
|
||||
uint8_t touch_count = td_status & 0x0F;
|
||||
return touch_count > 0;
|
||||
}
|
||||
|
||||
uint8_t ft6336u_get_chip_id(void) {
|
||||
if (g_config == NULL) return 0xFF;
|
||||
|
||||
uint8_t chip_id;
|
||||
if (!ft6336u_read_reg(FT6336U_REG_CHIPID, &chip_id)) {
|
||||
return 0xFF;
|
||||
}
|
||||
return chip_id;
|
||||
}
|
||||
|
||||
uint8_t ft6336u_get_firmware_version(void) {
|
||||
if (g_config == NULL) return 0xFF;
|
||||
|
||||
uint8_t fw_ver;
|
||||
if (!ft6336u_read_reg(FT6336U_REG_FIRMID, &fw_ver)) {
|
||||
return 0xFF;
|
||||
}
|
||||
return fw_ver;
|
||||
}
|
||||
|
||||
void ft6336u_set_interrupt_callback(void (*callback)(uint gpio, uint32_t events)) {
|
||||
if (g_config == NULL || callback == NULL) return;
|
||||
|
||||
// Enable interrupt on falling edge (touch detected)
|
||||
gpio_set_irq_enabled_with_callback(g_config->gpio_int,
|
||||
GPIO_IRQ_EDGE_FALL,
|
||||
true,
|
||||
callback);
|
||||
}
|
||||
|
||||
bool ft6336u_test_i2c(void) {
|
||||
if (g_config == NULL) {
|
||||
printf("[FT6336U] Test failed: not initialized\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("[FT6336U] Testing I2C communication...\n");
|
||||
|
||||
// Test 1: Read chip ID
|
||||
uint8_t chip_id = ft6336u_get_chip_id();
|
||||
printf(" Chip ID: 0x%02X (expected 0x64) - %s\n",
|
||||
chip_id, chip_id == 0x64 ? "PASS" : "FAIL");
|
||||
|
||||
// Test 2: Read firmware version
|
||||
uint8_t fw_ver = ft6336u_get_firmware_version();
|
||||
printf(" Firmware: 0x%02X - %s\n",
|
||||
fw_ver, fw_ver != 0xFF ? "PASS" : "FAIL");
|
||||
|
||||
// Test 3: Read TD_STATUS multiple times
|
||||
int success_count = 0;
|
||||
const int test_count = 10;
|
||||
for (int i = 0; i < test_count; i++) {
|
||||
uint8_t status;
|
||||
if (ft6336u_read_reg(FT6336U_REG_TD_STATUS, &status)) {
|
||||
success_count++;
|
||||
}
|
||||
sleep_ms(10);
|
||||
}
|
||||
printf(" TD_STATUS reads: %d/%d successful - %s\n",
|
||||
success_count, test_count,
|
||||
success_count == test_count ? "PASS" : "WARN");
|
||||
|
||||
bool overall = (chip_id == 0x64) && (fw_ver != 0xFF) && (success_count >= test_count - 2);
|
||||
printf("[FT6336U] I2C test: %s\n", overall ? "PASS" : "FAIL");
|
||||
|
||||
return overall;
|
||||
}
|
||||
@@ -38,9 +38,15 @@ extern "C" {
|
||||
#define FT6336U_REG_P2_MISC 0x0E
|
||||
|
||||
#define FT6336U_REG_CHIPID 0xA3 // Chip ID (should read 0x64)
|
||||
#define FT6336U_REG_G_MODE 0xA4 // Interrupt mode (polling or trigger)
|
||||
#define FT6336U_REG_POWER_MODE 0xA5 // Power mode
|
||||
#define FT6336U_REG_FIRMID 0xA6
|
||||
#define FT6336U_REG_VENDID 0xA8
|
||||
|
||||
// G_MODE values
|
||||
#define FT6336U_G_MODE_POLLING 0x00
|
||||
#define FT6336U_G_MODE_TRIGGER 0x01
|
||||
|
||||
// Touch event types
|
||||
#define FT6336U_EVENT_PRESS_DOWN 0x00
|
||||
#define FT6336U_EVENT_LIFT_UP 0x01
|
||||
@@ -56,7 +62,8 @@ typedef struct {
|
||||
uint16_t y;
|
||||
uint8_t event; // Press down, lift up, contact, no event
|
||||
uint8_t id; // Touch point ID
|
||||
uint8_t weight; // Touch pressure/area
|
||||
uint8_t weight; // Touch pressure/area (0-255)
|
||||
uint8_t misc; // Touch area (0-15, upper nibble of MISC register)
|
||||
} ft6336u_touch_point_t;
|
||||
|
||||
// Touch data structure
|
||||
@@ -124,6 +131,25 @@ void ft6336u_set_interrupt_callback(void (*callback)(uint gpio, uint32_t events)
|
||||
*/
|
||||
bool ft6336u_test_i2c(void);
|
||||
|
||||
/**
|
||||
* Set G_MODE register (polling vs trigger mode)
|
||||
* @param mode 0 for polling mode, 1 for trigger mode
|
||||
* @return true if successful
|
||||
*/
|
||||
bool ft6336u_set_g_mode(uint8_t mode);
|
||||
|
||||
/**
|
||||
* Get current G_MODE setting
|
||||
* @return Current G_MODE value or 0xFF on error
|
||||
*/
|
||||
uint8_t ft6336u_get_g_mode(void);
|
||||
|
||||
/**
|
||||
* Get current power mode
|
||||
* @return Current power mode or 0xFF on error
|
||||
*/
|
||||
uint8_t ft6336u_get_power_mode(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static sd_card_config_t g_config_storage;
|
||||
static const sd_card_config_t *g_config = NULL;
|
||||
static sd_card_info_t g_card_info = {0};
|
||||
|
||||
@@ -91,7 +92,9 @@ static uint8_t sd_card_send_acmd(uint8_t acmd, uint32_t arg) {
|
||||
bool sd_card_init(const sd_card_config_t *config) {
|
||||
if (config == NULL) return false;
|
||||
|
||||
g_config = config;
|
||||
// Copy config to static storage to avoid dangling pointer
|
||||
memcpy(&g_config_storage, config, sizeof(sd_card_config_t));
|
||||
g_config = &g_config_storage;
|
||||
memset(&g_card_info, 0, sizeof(g_card_info));
|
||||
|
||||
// Initialize CS pin (active low)
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
|
||||
// Global state variables
|
||||
// These hold the current display configuration
|
||||
static struct st7796_config config_storage; // Static storage for config copy
|
||||
static const struct st7796_config *config; // Pin and SPI configuration
|
||||
static uint16_t width; // Display width in pixels (e.g., 480)
|
||||
static uint16_t height; // Display height in pixels (e.g., 320)
|
||||
@@ -321,7 +322,9 @@ static void set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||
* @param h Display height (320 for landscape)
|
||||
*/
|
||||
void st7796_init(const struct st7796_config *c, uint16_t w, uint16_t h) {
|
||||
config = c;
|
||||
// Copy config to static storage to avoid dangling pointer
|
||||
memcpy(&config_storage, c, sizeof(struct st7796_config));
|
||||
config = &config_storage;
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
@@ -401,10 +404,10 @@ void st7796_init(const struct st7796_config *c, uint16_t w, uint16_t h) {
|
||||
write_command_with_data(ST7796_MADCTL, &data, 1);
|
||||
sleep_ms(10);
|
||||
|
||||
// Display Inversion - try OFF first
|
||||
// Some displays look better with INVON, others with INVOFF
|
||||
// If colors look wrong, try: write_command(ST7796_INVON);
|
||||
write_command(ST7796_INVOFF);
|
||||
// Display Inversion - try ON for displays that need it
|
||||
// Some displays need INVON, others need INVOFF
|
||||
// If this doesn't work, try: write_command(ST7796_INVOFF);
|
||||
write_command(ST7796_INVON);
|
||||
sleep_ms(10);
|
||||
|
||||
// Normal Display Mode On
|
||||
|
||||
Reference in New Issue
Block a user