Например TDA7294

Форум РадиоКот • Просмотр темы - Помогите запустить дисплей SP14Q002-A (320*240)
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Вс сен 21, 2025 15:49:33

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 2 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Помогите запустить дисплей SP14Q002-A (320*240)
СообщениеДобавлено: Ср сен 17, 2025 17:21:30 
Друг Кота
Аватар пользователя

Карма: 13
Рейтинг сообщений: 79
Зарегистрирован: Пн авг 10, 2009 01:18:55
Сообщений: 4100
Откуда: Электросталь
Рейтинг сообщения: 0
Привет!
имеется такой вот дисплей SP14Q002-A, весьма себе замечательный и еще и размеров приличных
даташит
https://datasheet.octopart.com/SP14Q002 ... 835662.pdf

дисплей подключен так

Arduino Due -> (LCD Display)
D2 -> (CP)
D3 -> (LOAD)
D4 -> (FRAME)
D5 -> (DISP_OFF)
D6 -> (D0)
D7 -> (D1)
D8 -> (D2)
D9 -> (D3)

т.к. в программировании я особо не силен, уже несколько дней пытаюсь застравить чат жпт и дипсик помочь мне с этим делом.
В итоге имеем 2 скетча, но картинка форматируется неверно

Код:
// ----------
// Arduino Due -> 4-bit LCD Display
// Исправленный порядок бит, тестовые паттерны
// ----------

// Пины подключения
#define CP_PIN       2
#define LOAD_PIN     3
#define FRAME_PIN    4
#define DISP_OFF_PIN 5
#define D0_PIN       6
#define D1_PIN       7
#define D2_PIN       8
#define D3_PIN       9

// Разрешение дисплея
#define X_RES 320
#define Y_RES 240
#define BYTES_PER_LINE 80 // 4 пикселя на байт

// Прямой доступ к портам
#define PORT_CP    (g_APinDescription[CP_PIN].pPort->PIO_ODSR)
#define PORT_LOAD  (g_APinDescription[LOAD_PIN].pPort->PIO_ODSR)
#define PORT_FRAME (g_APinDescription[FRAME_PIN].pPort->PIO_ODSR)
#define PORT_D0    (g_APinDescription[D0_PIN].pPort->PIO_ODSR)
#define PORT_D1    (g_APinDescription[D1_PIN].pPort->PIO_ODSR)
#define PORT_D2    (g_APinDescription[D2_PIN].pPort->PIO_ODSR)
#define PORT_D3    (g_APinDescription[D3_PIN].pPort->PIO_ODSR)

#define MASK_CP    (g_APinDescription[CP_PIN].ulPin)
#define MASK_LOAD  (g_APinDescription[LOAD_PIN].ulPin)
#define MASK_FRAME (g_APinDescription[FRAME_PIN].ulPin)
#define MASK_D0    (g_APinDescription[D0_PIN].ulPin)
#define MASK_D1    (g_APinDescription[D1_PIN].ulPin)
#define MASK_D2    (g_APinDescription[D2_PIN].ulPin)
#define MASK_D3    (g_APinDescription[D3_PIN].ulPin)

// ----------
// Frame buffer
uint8_t frameBuffer[Y_RES][BYTES_PER_LINE];

// ----------
// Мини-задержка ~150ns
inline void shortDelay() {
  asm volatile(
    "nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"
  );
}

// Быстрый тактовый импульс CP
inline void pulseCP() {
  PORT_CP &= ~MASK_CP;
  shortDelay();
  PORT_CP |= MASK_CP;
  shortDelay();
}

// Быстрый импульс LOAD H->L
inline void pulseLOAD() {
  PORT_LOAD &= ~MASK_LOAD;
  shortDelay();
  PORT_LOAD |= MASK_LOAD;
  shortDelay();
}

// ----------
// Работа с пикселями
void setAllBlack() {
  for (int y = 0; y < Y_RES; y++)
    for (int x = 0; x < BYTES_PER_LINE; x++)
      frameBuffer[y][x] = 0x00;
}

// Установка пикселя с правильным порядком бит
void setPixel(int x, int y, bool state) {
  if (x < 0 || x >= X_RES || y < 0 || y >= Y_RES) return;
  int byteIndex = x / 4;
  int bitPosition = 3 - (x % 4); // D0 = старший бит первого пикселя
  if (state) frameBuffer[y][byteIndex] |= (1 << bitPosition);
  else       frameBuffer[y][byteIndex] &= ~(1 << bitPosition);
}

// ----------
// Тестовые паттерны
void drawGrid() {
  setAllBlack();
  // Вертикальные линии каждые 32 пикселя
  for (int x = 0; x < X_RES; x += 32)
    for (int y = 0; y < Y_RES; y++)
      setPixel(x, y, true);
  // Горизонтальные линии каждые 32 пикселя
  for (int y = 0; y < Y_RES; y += 32)
    for (int x = 0; x < X_RES; x++)
      setPixel(x, y, true);
  // Угловые маркеры
  setPixel(0, 0, true);
  setPixel(X_RES-1, 0, true);
  setPixel(0, Y_RES-1, true);
  setPixel(X_RES-1, Y_RES-1, true);
  // Центральный крест
  for (int x = X_RES/2-16; x < X_RES/2+16; x++)
    setPixel(x, Y_RES/2, true);
  for (int y = Y_RES/2-16; y < Y_RES/2+16; y++)
    setPixel(X_RES/2, y, true);
}

void drawPatternTest() {
  for (int y = 0; y < Y_RES; y++)
    for (int x = 0; x < X_RES; x++)
      setPixel(x, y, ((x/7 + y/8) % 2) == 0);
}

// ----------
// Отправка 4 бит на D0-D3
void send4Bits(uint8_t data) {
  if (data & 0x01) PORT_D0 |= MASK_D0; else PORT_D0 &= ~MASK_D0;
  if (data & 0x02) PORT_D1 |= MASK_D1; else PORT_D1 &= ~MASK_D1;
  if (data & 0x04) PORT_D2 |= MASK_D2; else PORT_D2 &= ~MASK_D2;
  if (data & 0x08) PORT_D3 |= MASK_D3; else PORT_D3 &= ~MASK_D3;
  pulseCP();
}

// ----------
// Отправка кадра
void displayFrame() {
  PORT_FRAME |= MASK_FRAME; // FRAME высокий для первой строки
  shortDelay();
  for (int y = 0; y < Y_RES; y++) {
    for (int x = 0; x < BYTES_PER_LINE; x++)
      send4Bits(frameBuffer[y][x]);
    pulseLOAD(); // фиксация линии
    if (y == 0) PORT_FRAME &= ~MASK_FRAME;
  }
}

// ----------
// Arduino setup
void setup() {
  pinMode(CP_PIN, OUTPUT);
  pinMode(LOAD_PIN, OUTPUT);
  pinMode(FRAME_PIN, OUTPUT);
  pinMode(DISP_OFF_PIN, OUTPUT);
  pinMode(D0_PIN, OUTPUT);
  pinMode(D1_PIN, OUTPUT);
  pinMode(D2_PIN, OUTPUT);
  pinMode(D3_PIN, OUTPUT);

  PORT_CP |= MASK_CP;
  PORT_LOAD |= MASK_LOAD;
  PORT_FRAME &= ~MASK_FRAME;
  digitalWrite(DISP_OFF_PIN, HIGH);

  // Выберите тестовый паттерн
  drawGrid();
   //drawPatternTest();
}

// ----------
// Arduino loop
void loop() {
  displayFrame(); // непрерывное обновление
}


формирует тестовые паттерны сетку и шахматку
но работает неочень и выглядит вот так
сетка не совсем сетка
Изображение
и шахматка не совсем шахматка
Изображение



и 2й скетч пытается выводить надпись hello world
Код:
// ----------
// Arduino Due -> 4-bit LCD Display
// HELLO WORLD жирным шрифтом, корректное отображение
// ----------

#define CP_PIN       2
#define LOAD_PIN     3
#define FRAME_PIN    4
#define DISP_OFF_PIN 5
#define D0_PIN       6
#define D1_PIN       7
#define D2_PIN       8
#define D3_PIN       9

#define X_RES 320
#define Y_RES 240
#define BYTES_PER_LINE 80 // 4 пикселя на байт

#define PORT_CP    (g_APinDescription[CP_PIN].pPort->PIO_ODSR)
#define PORT_LOAD  (g_APinDescription[LOAD_PIN].pPort->PIO_ODSR)
#define PORT_FRAME (g_APinDescription[FRAME_PIN].pPort->PIO_ODSR)
#define PORT_D0    (g_APinDescription[D0_PIN].pPort->PIO_ODSR)
#define PORT_D1    (g_APinDescription[D1_PIN].pPort->PIO_ODSR)
#define PORT_D2    (g_APinDescription[D2_PIN].pPort->PIO_ODSR)
#define PORT_D3    (g_APinDescription[D3_PIN].pPort->PIO_ODSR)

#define MASK_CP    (g_APinDescription[CP_PIN].ulPin)
#define MASK_LOAD  (g_APinDescription[LOAD_PIN].ulPin)
#define MASK_FRAME (g_APinDescription[FRAME_PIN].ulPin)
#define MASK_D0    (g_APinDescription[D0_PIN].ulPin)
#define MASK_D1    (g_APinDescription[D1_PIN].ulPin)
#define MASK_D2    (g_APinDescription[D2_PIN].ulPin)
#define MASK_D3    (g_APinDescription[D3_PIN].ulPin)

uint8_t frameBuffer[Y_RES][BYTES_PER_LINE];

// ----------
// Мини-задержка ~150ns
inline void shortDelay() {
  asm volatile("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
}

// Быстрый тактовый импульс CP
inline void pulseCP() {
  PORT_CP &= ~MASK_CP;
  shortDelay();
  PORT_CP |= MASK_CP;
  shortDelay();
}

// Быстрый импульс LOAD H->L
inline void pulseLOAD() {
  PORT_LOAD &= ~MASK_LOAD;
  shortDelay();
  PORT_LOAD |= MASK_LOAD;
  shortDelay();
}

// ----------
// Работа с пикселями
void setAllBlack() {
  for (int y = 0; y < Y_RES; y++)
    for (int x = 0; x < BYTES_PER_LINE; x++)
      frameBuffer[y][x] = 0x00;
}

void setPixel(int x, int y, bool state) {
  if (x < 0 || x >= X_RES || y < 0 || y >= Y_RES) return;
  int byteIndex = x / 4;
  int bitPosition = 3 - (x % 4); // D0 = старший бит первого пикселя
  if (state) frameBuffer[y][byteIndex] |= (1 << bitPosition);
  else       frameBuffer[y][byteIndex] &= ~(1 << bitPosition);
}

// ----------
// Отправка 4 бит на D0-D3
void send4Bits(uint8_t data) {
  if (data & 0x01) PORT_D0 |= MASK_D0; else PORT_D0 &= ~MASK_D0;
  if (data & 0x02) PORT_D1 |= MASK_D1; else PORT_D1 &= ~MASK_D1;
  if (data & 0x04) PORT_D2 |= MASK_D2; else PORT_D2 &= ~MASK_D2;
  if (data & 0x08) PORT_D3 |= MASK_D3; else PORT_D3 &= ~MASK_D3;
  pulseCP();
}

// ----------
// Отправка кадра
void displayFrame() {
  PORT_FRAME |= MASK_FRAME;
  shortDelay();
  for (int y = 0; y < Y_RES; y++) {
    for (int x = 0; x < BYTES_PER_LINE; x++)
      send4Bits(frameBuffer[y][x]);
    pulseLOAD();
    if (y == 0) PORT_FRAME &= ~MASK_FRAME;
  }
}

// ----------
// Жирный шрифт 16x16, горизонтальные байты для LCD
// Каждая строка = 16 бит, потом разбиваем на 4-битные пиксели
// Для примера: только буквы HELLO WORLD и пробел
const uint16_t font_H[16] = {
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111111111111111,
  0b1111111111111111,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001,
  0b1111000111110001
};

const uint16_t font_E[16] = {
  0b1111111111111111,
  0b1111111111111111,
  0b1111000000000000,
  0b1111000000000000,
  0b1111111111111110,
  0b1111111111111110,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111111111111111,
  0b1111111111111111,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000
};

const uint16_t font_L[16] = {
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111000000000000,
  0b1111111111111111,
  0b1111111111111111,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000
};

const uint16_t font_O[16] = {
  0b0111111111111110,
  0b1111111111111111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111111111111111,
  0b0111111111111110,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000
};

const uint16_t font_W[16] = {
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111000000001111,
  0b1111001100111111,
  0b1111001100111111,
  0b1111010010111111,
  0b1111010010111111,
  0b1111100001111111,
  0b1111100001111111,
  0b1111000000001111,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000
};

const uint16_t font_R[16] = {
  0b1111111111111000,
  0b1111111111111100,
  0b1111000000001110,
  0b1111000000000111,
  0b1111000000000111,
  0b1111111111111100,
  0b1111111111111000,
  0b1111001000000000,
  0b1111000100000000,
  0b1111000010000000,
  0b1111000001111000,
  0b1111000001111100,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000
};

const uint16_t font_D[16] = {
  0b1111111111110000,
  0b1111111111111000,
  0b1111000000011100,
  0b1111000000001100,
  0b1111000000000110,
  0b1111000000000110,
  0b1111000000000110,
  0b1111000000000110,
  0b1111000000001100,
  0b1111000000011000,
  0b1111111111111000,
  0b1111111111110000,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000,
  0b0000000000000000
};

const uint16_t font_space[16] = {0};

// ----------
// Рисуем символ на LCD
void drawChar16x16_LCD(int x0, int y0, const uint16_t* bitmap) {
  for (int y = 0; y < 16; y++) {
    for (int x = 0; x < 16; x++) {
      bool pixel = bitmap[y] & (1 << (15 - x));
      setPixel(x0 + x, y0 + y, pixel);
      // Жирный: дублируем пиксель справа
      setPixel(x0 + x + 1, y0 + y, pixel);
    }
  }
}

// ----------
// Рисуем строку HELLO WORLD
void drawHelloWorld_LCD(int x0, int y0) {
  const uint16_t* chars[] = {font_H, font_E, font_L, font_L, font_O, font_space,
                             font_W, font_O, font_R, font_L, font_D};
  int px = x0;
  for (int i = 0; i < 11; i++) {
    drawChar16x16_LCD(px, y0, chars[i]);
    px += 18; // шаг между символами
  }
}

// ----------
// Setup & loop
void setup() {
  pinMode(CP_PIN, OUTPUT);
  pinMode(LOAD_PIN, OUTPUT);
  pinMode(FRAME_PIN, OUTPUT);
  pinMode(DISP_OFF_PIN, OUTPUT);
  pinMode(D0_PIN, OUTPUT);
  pinMode(D1_PIN, OUTPUT);
  pinMode(D2_PIN, OUTPUT);
  pinMode(D3_PIN, OUTPUT);

  PORT_CP |= MASK_CP;
  PORT_LOAD |= MASK_LOAD;
  PORT_FRAME &= ~MASK_FRAME;
  digitalWrite(DISP_OFF_PIN, HIGH);

  setAllBlack();
  drawHelloWorld_LCD(50, 100); // координаты для центрирования
}

void loop() {
  displayFrame();
}


ну и тут с отображением все не так как надо
Изображение

и + ко всему картинка и там и там дико мерцает
подскажите как пофиксить :tea:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите запустить дисплей SP14Q002-A (320*240)
СообщениеДобавлено: Пт сен 19, 2025 20:36:21 
Друг Кота
Аватар пользователя

Карма: 13
Рейтинг сообщений: 79
Зарегистрирован: Пн авг 10, 2009 01:18:55
Сообщений: 4100
Откуда: Электросталь
Рейтинг сообщения: 0
Ну куда все умные коты подевались?

подскажите чего не так

Код:
// ----------
// Arduino Due -> Hitachi SP14Q002-A1
// 4 части экрана с надписями
// Исправлена синхронизация
// ----------

#define CP_PIN       2
#define LOAD_PIN     3
#define FRAME_PIN    4
#define DISP_OFF_PIN 5
#define D0_PIN       6
#define D1_PIN       7
#define D2_PIN       8
#define D3_PIN       9

#define X_RES 320
#define Y_RES 240
#define BYTES_PER_LINE (X_RES / 8)

// Прямое управление портами для максимальной скорости
#define PORT_CP    (g_APinDescription[CP_PIN].pPort)
#define PORT_LOAD  (g_APinDescription[LOAD_PIN].pPort)
#define PORT_FRAME (g_APinDescription[FRAME_PIN].pPort)
#define PORT_D0    (g_APinDescription[D0_PIN].pPort)
#define PORT_D1    (g_APinDescription[D1_PIN].pPort)
#define PORT_D2    (g_APinDescription[D2_PIN].pPort)
#define PORT_D3    (g_APinDescription[D3_PIN].pPort)

#define MASK_CP    (g_APinDescription[CP_PIN].ulPin)
#define MASK_LOAD  (g_APinDescription[LOAD_PIN].ulPin)
#define MASK_FRAME (g_APinDescription[FRAME_PIN].ulPin)
#define MASK_D0    (g_APinDescription[D0_PIN].ulPin)
#define MASK_D1    (g_APinDescription[D1_PIN].ulPin)
#define MASK_D2    (g_APinDescription[D2_PIN].ulPin)
#define MASK_D3    (g_APinDescription[D3_PIN].ulPin)

// Буфер для всего экрана
uint8_t frameBuffer[Y_RES][BYTES_PER_LINE];

// ----------
// Ультрабыстрые функции для работы с пинами
inline void setCP(bool state) {
  if (state) PORT_CP->PIO_SODR = MASK_CP;
  else PORT_CP->PIO_CODR = MASK_CP;
  asm volatile("nop\n nop\n");
}

inline void setLOAD(bool state) {
  if (state) PORT_LOAD->PIO_SODR = MASK_LOAD;
  else PORT_LOAD->PIO_CODR = MASK_LOAD;
  asm volatile("nop\n nop\n");
}

inline void setFRAME(bool state) {
  if (state) PORT_FRAME->PIO_SODR = MASK_FRAME;
  else PORT_FRAME->PIO_CODR = MASK_FRAME;
  asm volatile("nop\n nop\n");
}

inline void setDataPinsFast(uint8_t data) {
  uint32_t portState = PORT_D0->PIO_ODSR;
  portState = (portState & ~(MASK_D0 | MASK_D1 | MASK_D2 | MASK_D3)) |
              ((data & 0x01) ? MASK_D0 : 0) |
              ((data & 0x02) ? MASK_D1 : 0) |
              ((data & 0x04) ? MASK_D2 : 0) |
              ((data & 0x08) ? MASK_D3 : 0);
  PORT_D0->PIO_ODSR = portState;
  asm volatile("nop\n nop\n");
}

// ----------
// Быстрая отправка 4 пикселей
inline void send4PixelsFast(uint8_t pixels) {
  setDataPinsFast(pixels);
  setCP(false);
  asm volatile("nop\n nop\n");
  setCP(true);
  asm volatile("nop\n nop\n");
}

// ----------
// Быстрая отправка байта
inline void sendByteFast(uint8_t byteData) {
  send4PixelsFast((byteData >> 4) & 0x0F);
  send4PixelsFast(byteData & 0x0F);
}

// ----------
// Инициализация дисплея
void initDisplay() {
  for (int i = 2; i <= 9; i++) {
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }
 
  digitalWrite(DISP_OFF_PIN, LOW);
  delay(100);
 
  digitalWrite(CP_PIN, HIGH);
  digitalWrite(LOAD_PIN, HIGH);
  digitalWrite(FRAME_PIN, LOW);
  digitalWrite(DISP_OFF_PIN, HIGH);
 
  delay(50);
}

// ----------
// Очистка экрана
void clearScreen() {
  memset(frameBuffer, 0, sizeof(frameBuffer));
}

// ----------
// Установка пикселя
void setPixel(int x, int y, bool state) {
  if (x < 0 || x >= X_RES || y < 0 || y >= Y_RES) return;

  int byteIndex = x / 8;
  int bitPos = 7 - (x % 8);

  if (state) {
    frameBuffer[y][byteIndex] |= (1 << bitPos);
  } else {
    frameBuffer[y][byteIndex] &= ~(1 << bitPos);
  }
}

// ----------
// Рисование линии
void drawLine(int x1, int y1, int x2, int y2, bool state) {
  int dx = abs(x2 - x1);
  int dy = abs(y2 - y1);
  int sx = (x1 < x2) ? 1 : -1;
  int sy = (y1 < y2) ? 1 : -1;
  int err = dx - dy;

  while (true) {
    setPixel(x1, y1, state);
    if (x1 == x2 && y1 == y2) break;
    int e2 = 2 * err;
    if (e2 > -dy) {
      err -= dy;
      x1 += sx;
    }
    if (e2 < dx) {
      err += dx;
      y1 += sy;
    }
  }
}

// ----------
// Рисование прямоугольника
void drawRect(int x1, int y1, int x2, int y2, bool state) {
  drawLine(x1, y1, x2, y1, state);
  drawLine(x2, y1, x2, y2, state);
  drawLine(x2, y2, x1, y2, state);
  drawLine(x1, y2, x1, y1, state);
}

// ----------
// Простой шрифт 5x7
const uint8_t font_5x7[][5] = {
  {0x00,0x00,0x00,0x00,0x00}, // space
  {0x00,0x00,0x5F,0x00,0x00}, // !
  {0x00,0x07,0x00,0x07,0x00}, // "
  {0x14,0x7F,0x14,0x7F,0x14}, // #
  {0x24,0x2A,0x7F,0x2A,0x12}, // $
  {0x23,0x13,0x08,0x64,0x62}, // %
  {0x36,0x49,0x55,0x22,0x50}, // &
  {0x00,0x05,0x03,0x00,0x00}, // '
  {0x00,0x1C,0x22,0x41,0x00}, // (
  {0x00,0x41,0x22,0x1C,0x00}, // )
  {0x14,0x08,0x3E,0x08,0x14}, // *
  {0x08,0x08,0x3E,0x08,0x08}, // +
  {0x00,0x50,0x30,0x00,0x00}, // ,
  {0x08,0x08,0x08,0x08,0x08}, // -
  {0x00,0x60,0x60,0x00,0x00}, // .
  {0x20,0x10,0x08,0x04,0x02}, // /
  {0x3E,0x51,0x49,0x45,0x3E}, // 0
  {0x00,0x42,0x7F,0x40,0x00}, // 1
  {0x42,0x61,0x51,0x49,0x46}, // 2
  {0x21,0x41,0x45,0x4B,0x31}, // 3
  {0x18,0x14,0x12,0x7F,0x10}, // 4
  {0x27,0x45,0x45,0x45,0x39}, // 5
  {0x3C,0x4A,0x49,0x49,0x30}, // 6
  {0x01,0x71,0x09,0x05,0x03}, // 7
  {0x36,0x49,0x49,0x49,0x36}, // 8
  {0x06,0x49,0x49,0x29,0x1E}, // 9
  {0x00,0x36,0x36,0x00,0x00}, // :
  {0x00,0x56,0x36,0x00,0x00}, // ;
  {0x08,0x14,0x22,0x41,0x00}, // <
  {0x14,0x14,0x14,0x14,0x14}, // =
  {0x00,0x41,0x22,0x14,0x08}, // >
  {0x02,0x01,0x51,0x09,0x06}, // ?
  {0x32,0x49,0x79,0x41,0x3E}, // @
  {0x7E,0x11,0x11,0x11,0x7E}, // A
  {0x7F,0x49,0x49,0x49,0x36}, // B
  {0x3E,0x41,0x41,0x41,0x22}, // C
  {0x7F,0x41,0x41,0x22,0x1C}, // D
  {0x7F,0x49,0x49,0x49,0x41}, // E
  {0x7F,0x09,0x09,0x09,0x01}, // F
  {0x3E,0x41,0x49,0x49,0x7A}, // G
  {0x7F,0x08,0x08,0x08,0x7F}, // H
  {0x00,0x41,0x7F,0x41,0x00}, // I
  {0x20,0x40,0x41,0x3F,0x01}, // J
  {0x7F,0x08,0x14,0x22,0x41}, // K
  {0x7F,0x40,0x40,0x40,0x40}, // L
  {0x7F,0x02,0x0C,0x02,0x7F}, // M
  {0x7F,0x04,0x08,0x10,0x7F}, // N
  {0x3E,0x41,0x41,0x41,0x3E}, // O
  {0x7F,0x09,0x09,0x09,0x06}, // P
  {0x3E,0x41,0x51,0x21,0x5E}, // Q
  {0x7F,0x09,0x19,0x29,0x46}, // R
  {0x46,0x49,0x49,0x49,0x31}, // S
  {0x01,0x01,0x7F,0x01,0x01}, // T
  {0x3F,0x40,0x40,0x40,0x3F}, // U
  {0x1F,0x20,0x40,0x20,0x1F}, // V
  {0x3F,0x40,0x38,0x40,0x3F}, // W
  {0x63,0x14,0x08,0x14,0x63}, // X
  {0x07,0x08,0x70,0x08,0x07}, // Y
  {0x61,0x51,0x49,0x45,0x43}, // Z
};

void drawChar5x7(int x, int y, char c) {
  if (c < 32 || c > 90) c = ' '; // только заглавные буквы и цифры
  const uint8_t* glyph = font_5x7[c - 32];
 
  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 7; j++) {
      if (glyph[i] & (1 << j)) {
        setPixel(x + i, y + j, true);
      }
    }
  }
}

void drawText(int x, int y, const char* text) {
  int startX = x;
  while (*text) {
    if (*text == '\n') {
      y += 8;
      x = startX;
    } else {
      drawChar5x7(x, y, *text);
      x += 6;
    }
    text++;
  }
}

// ----------
// Создаем 4 части экрана с надписями
void createFourQuadrants() {
  clearScreen();
 
  // Центральные линии, делящие экран на 4 части
  drawLine(X_RES/2, 0, X_RES/2, Y_RES-1, true);
  drawLine(0, Y_RES/2, X_RES-1, Y_RES/2, true);
 
  // Толстые границы
  drawRect(2, 2, X_RES-3, Y_RES-3, true);
  drawRect(4, 4, X_RES-5, Y_RES-5, true);
 
  // Надписи в каждой четверти
  drawText(30, 30, "TOP-LEFT");
  drawText(X_RES/2 + 30, 30, "TOP-RIGHT");
  drawText(30, Y_RES/2 + 30, "BOT-LEFT");
  drawText(X_RES/2 + 30, Y_RES/2 + 30, "BOT-RIGHT");
 
  // Дополнительные элементы для визуализации
  for (int i = 0; i < 4; i++) {
    int qx = (i % 2) * (X_RES/2);
    int qy = (i / 2) * (Y_RES/2);
   
    // Угловые маркеры
    drawRect(qx + 10, qy + 10, qx + 20, qy + 20, true);
    drawRect(qx + X_RES/2 - 20, qy + 10, qx + X_RES/2 - 10, qy + 20, true);
    drawRect(qx + 10, qy + Y_RES/2 - 20, qx + 20, qy + Y_RES/2 - 10, true);
    drawRect(qx + X_RES/2 - 20, qy + Y_RES/2 - 20, qx + X_RES/2 - 10, qy + Y_RES/2 - 10, true);
   
    // Диагональные линии в каждой четверти
    drawLine(qx + 5, qy + 5, qx + X_RES/2 - 5, qy + Y_RES/2 - 5, true);
  }
}

// ----------
// Правильная отправка кадра с исправленной синхронизацией
void displayFrameCorrect() {
  // Начало кадра - FRAME pulse (должен быть ДО первой строки)
  setFRAME(true);
  asm volatile("nop\n nop\n nop\n nop\n nop\n nop\n");
 
  for (int y = 0; y < Y_RES; y++) {
    // Отправляем всю строку
    for (int x = 0; x < BYTES_PER_LINE; x++) {
      sendByteFast(frameBuffer[y][x]);
    }
   
    // Завершение строки - LOAD pulse
    setLOAD(false);
    asm volatile("nop\n nop\n nop\n nop\n");
    setLOAD(true);
    asm volatile("nop\n nop\n");

    // Сбрасываем FRAME после отправки первой строки
    if (y == 0) {
      setFRAME(false);
      asm volatile("nop\n nop\n nop\n nop\n");
    }
  }
}

// ----------
// Setup & loop
void setup() {
  initDisplay();
  createFourQuadrants();
  delay(1000);
}

void loop() {
  displayFrameCorrect();
 
  // Мигание центральной точки для индикации работы
  static unsigned long lastBlink = 0;
  static bool blinkState = false;
 
  if (millis() - lastBlink > 500) {
    blinkState = !blinkState;
    setPixel(X_RES/2, Y_RES/2, blinkState);
    lastBlink = millis();
  }
 
  delayMicroseconds(500);
}


Изображение


и вот

Код:
// ----------
// Arduino Due -> Hitachi SP14Q002-A1
// Исправлено: вывод текста на весь экран
// Тест: вывод "HELLO WORLD"
// ----------

#define CP_PIN       2
#define LOAD_PIN     3
#define FRAME_PIN    4
#define DISP_OFF_PIN 5
#define D0_PIN       6
#define D1_PIN       7
#define D2_PIN       8
#define D3_PIN       9

#define X_RES 320
#define Y_RES 240
#define HALF_X_RES 160   // одна половина строки
#define NIBBLES_PER_LINE (HALF_X_RES / 4)
#define BYTES_PER_LINE   (NIBBLES_PER_LINE / 2)

// Правильные определения для работы с портами
#define PORT_CP    (g_APinDescription[CP_PIN].pPort)
#define PORT_LOAD  (g_APinDescription[LOAD_PIN].pPort)
#define PORT_FRAME (g_APinDescription[FRAME_PIN].pPort)
#define PORT_D0    (g_APinDescription[D0_PIN].pPort)
#define PORT_D1    (g_APinDescription[D1_PIN].pPort)
#define PORT_D2    (g_APinDescription[D2_PIN].pPort)
#define PORT_D3    (g_APinDescription[D3_PIN].pPort)

#define MASK_CP    (g_APinDescription[CP_PIN].ulPin)
#define MASK_LOAD  (g_APinDescription[LOAD_PIN].ulPin)
#define MASK_FRAME (g_APinDescription[FRAME_PIN].ulPin)
#define MASK_D0    (g_APinDescription[D0_PIN].ulPin)
#define MASK_D1    (g_APinDescription[D1_PIN].ulPin)
#define MASK_D2    (g_APinDescription[D2_PIN].ulPin)
#define MASK_D3    (g_APinDescription[D3_PIN].ulPin)

// ----------
// Буфер для **всего экрана**
uint8_t frameBuffer[Y_RES][HALF_X_RES/4]; // храним половину строки, будем дублировать при отправке

// ----------
// Мини-задержка ~200ns
inline void shortDelay() {
  asm volatile("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
}

// ----------
// Установка состояния пина
inline void setPin(Pio* port, uint32_t mask, bool state) {
  if (state) {
    port->PIO_SODR = mask;
  } else {
    port->PIO_CODR = mask;
  }
}

// ----------
// Отправка 4 пикселей (D0..D3)
inline void send4Pixels(uint8_t pixels) {
  setPin(PORT_D0, MASK_D0, pixels & 0x01);
  setPin(PORT_D1, MASK_D1, pixels & 0x02);
  setPin(PORT_D2, MASK_D2, pixels & 0x04);
  setPin(PORT_D3, MASK_D3, pixels & 0x08);

  shortDelay();
  setPin(PORT_CP, MASK_CP, false);
  shortDelay();
  setPin(PORT_CP, MASK_CP, true);
  shortDelay();
}

// ----------
// Очистка экрана
void setAllBlack() {
  for (int y = 0; y < Y_RES; y++) {
    for (int x = 0; x < HALF_X_RES/4; x++) {
      frameBuffer[y][x] = 0x00;
    }
  }
}

// ----------
// Установка пикселя (координаты 0..319)
void setPixel(int x, int y, bool state) {
  if (x < 0 || x >= X_RES || y < 0 || y >= Y_RES) return;

  // Переводим координаты в индекс буфера половины строки
  int x_half = x % HALF_X_RES;
  int byteIndex = x_half / 8;
  int bitPos = 7 - (x_half % 8);

  if (byteIndex < BYTES_PER_LINE) {
    if (state) frameBuffer[y][byteIndex] |= (1 << bitPos);
    else       frameBuffer[y][byteIndex] &= ~(1 << bitPos);
  }
}

// ----------
// Отправка кадра
void displayFrame() {
  setPin(PORT_FRAME, MASK_FRAME, true);
  shortDelay();
  shortDelay();

  for (int y = 0; y < Y_RES; y++) {
    for (int half = 0; half < 2; half++) { // левая и правая половины
      for (int x = 0; x < BYTES_PER_LINE; x++) {
        uint8_t byteData = frameBuffer[y][x];
        send4Pixels((byteData >> 4) & 0x0F);
        send4Pixels(byteData & 0x0F);
      }
    }
    shortDelay();
    setPin(PORT_LOAD, MASK_LOAD, false);
    shortDelay();
    shortDelay();
    setPin(PORT_LOAD, MASK_LOAD, true);
    shortDelay();

    if (y == 0) {
      shortDelay();
      setPin(PORT_FRAME, MASK_FRAME, false);
    }
  }
}

// ----------
// Шрифты 8x16
const uint8_t font_H[16] = {0b11111111,0b11111111,0b11000011,0b11000011,0b11000011,0b11000011,0b11111111,0b11111111,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11111111,0b11111111};
const uint8_t font_E[16] = {0b11111111,0b11111111,0b11000000,0b11000000,0b11000000,0b11111110,0b11111110,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11111111,0b11111111,0b00000000,0b00000000};
const uint8_t font_L[16] = {0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11111111,0b11111111,0b00000000,0b00000000};
const uint8_t font_O[16] = {0b01111110,0b11111111,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11111111,0b01111110,0b00000000,0b00000000};
const uint8_t font_W[16] = {0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11011011,0b11011011,0b11111111,0b11100111,0b11100111,0b11000011,0b00000000,0b00000000,0b00000000,0b00000000};
const uint8_t font_R[16] = {0b11111110,0b11111111,0b11000011,0b11000011,0b11000011,0b11111111,0b11111110,0b11011100,0b11001110,0b11000111,0b11000011,0b11000001,0b00000000,0b00000000,0b00000000,0b00000000};
const uint8_t font_D[16] = {0b11111100,0b11111110,0b11000111,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000111,0b11111110,0b11111100,0b00000000,0b00000000,0b00000000,0b00000000};
const uint8_t font_space[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

// ----------
// Рисуем символ 8x16
void drawChar8x16(int x0, int y0, const uint8_t* bitmap) {
  for (int y = 0; y < 16; y++) {
    for (int x = 0; x < 8; x++) {
      bool pixel = (bitmap[y] >> (7 - x)) & 0x01;
      setPixel(x0 + x, y0 + y, pixel);
    }
  }
}

// ----------
// Рисуем строку
void drawString(const char* str, int x0, int y0) {
  int px = x0;
  for (int i = 0; str[i]; i++) {
    const uint8_t* glyph = font_space;
    switch (str[i]) {
      case 'H': glyph = font_H; break;
      case 'E': glyph = font_E; break;
      case 'L': glyph = font_L; break;
      case 'O': glyph = font_O; break;
      case 'W': glyph = font_W; break;
      case 'R': glyph = font_R; break;
      case 'D': glyph = font_D; break;
      case ' ': glyph = font_space; break;
    }
    drawChar8x16(px, y0, glyph);
    px += 10;
  }
}

// ----------
// Рисуем тестовую сетку для отладки
void drawTestPattern() {
  setAllBlack();
  for (int x = 0; x < X_RES; x++) { setPixel(x, 0, true); setPixel(x, Y_RES-1, true); }
  for (int y = 0; y < Y_RES; y++) { setPixel(0, y, true); setPixel(X_RES-1, y, true); setPixel(HALF_X_RES, y, true); }
  drawString("HELLO WORLD", 20, 100);
}

// ----------
// Setup & loop
void setup() {
  pinMode(CP_PIN, OUTPUT); pinMode(LOAD_PIN, OUTPUT); pinMode(FRAME_PIN, OUTPUT);
  pinMode(DISP_OFF_PIN, OUTPUT); pinMode(D0_PIN, OUTPUT); pinMode(D1_PIN, OUTPUT);
  pinMode(D2_PIN, OUTPUT); pinMode(D3_PIN, OUTPUT);

  digitalWrite(CP_PIN, HIGH); digitalWrite(LOAD_PIN, HIGH);
  digitalWrite(FRAME_PIN, LOW); digitalWrite(DISP_OFF_PIN, HIGH);

  drawTestPattern();
}

void loop() {
  displayFrame();
  delay(20);
}


Изображение



даташит

https://datasheet.octopart.com/SP14Q002 ... 835662.pdf


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 2 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y