Инициализация дисплея ST7789v2

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

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

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

Datasheet

#include <SPI.h>

uint8_t csPin, dcPin, rstPin;

#define SCR_WD  240
#define SCR_HT  280

#define dcPin   8
#define csPin   9
#define rstPin  7

#define CS_HIGH   digitalWrite(csPin, HIGH)
#define CS_LOW    digitalWrite(csPin, LOW)
#define DC_HIGH   digitalWrite(dcPin, HIGH)
#define DC_LOW    digitalWrite(dcPin, LOW)

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#define ST7789_SWRESET   0x01  //SWRESET: Software reset
#define ST7789_NORON     0x13  //NORON: Partial off
#define ST7789_DISPOFF   0x28  //DISPOFF: Display off
#define ST7789_DISPON    0x29  //DISPON: Display on
#define ST7789_SLPIN     0x10  //SLPIN: Sleep in
#define ST7789_SLPOUT    0x11  //SLPOUT: Sleep out
#define ST7789_MADCTL    0x36  //MADCTL: memory data access control Old: 0x88
#define ST7789_COLMOD    0x3A  //COLMOD: Interface Pixel format (18-bits per pixel @ 262K colors)
#define ST7789_PORCTRK   0xB2  //PORCTRK: Porch setting
#define ST7789_GCTRL     0xB7  //GCTRL: Gate Control
#define ST7789_VCOMS     0xBB  //VCOMS: VCOM setting
#define ST7789_LCMCTRL   0xC0  //LCMCTRL: LCM Control
#define ST7789_VDVVRHEN  0xC2  //VDVVRHEN: VDV and VRH Command Enable
#define ST7789_VRHS      0xC3  //VRHS: VRH set
#define ST7789_VDVS      0xC4  //VDVS: VDV Set
#define ST7789_FRCTRL2   0xC6  //FRCTRL2: Frame Rate control in normal mode
#define ST7789_PWCTRL1   0xD0  //PWCTRL1: Power Control 1
#define ST7789_PVGAMCTRL 0xE0  //PVGAMCTRL: Positive Voltage Gamma Control
#define ST7789_NVGAMCTRL 0xE1  //NVGAMCTRL: Negative Voltage Gamma control
#define ST7789_CASET     0x2A  //CASET: X address set
#define ST7789_RASET     0x2B  //RASET: Y address set
#define ST7789_RAMWR     0x2C  //RAMWR: Memory write

inline void sendSPI(uint8_t v)
{
  SPI.transfer(v);
}

inline void sendCmd(uint8_t cmd)
{
  SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
  CS_LOW;
  DC_LOW;
  sendSPI(cmd);
  CS_HIGH;
  DC_HIGH;
  SPI.endTransaction();
}

inline void sendData(uint8_t data)
{
  SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
  CS_LOW;
  DC_HIGH;
  sendSPI(data);
  CS_HIGH;
  DC_LOW;
  SPI.endTransaction();
}

void initDisplay(){
  pinMode(dcPin, OUTPUT);
  pinMode(csPin, OUTPUT);
  pinMode(rstPin, OUTPUT);
  digitalWrite(rstPin, HIGH);
  delay(120);

  SPI.begin();
  //SPI.setDataMode(SPI_MODE0);
  //SPI.setClockDivider(SPI_CLOCK_DIV2);
  //SPI.setBitOrder(MSBFIRST);
  
  sendCmd(ST7789_SWRESET);
  delay(150);
  
  sendCmd(ST7789_SLPOUT);
  delay(255);

  sendCmd(ST7789_COLMOD);
  sendData(0x06);
  delay(10);

  sendCmd(ST7789_MADCTL);
  sendData(0x14);
  delay(150);

  sendCmd(ST7789_NORON);
  delay(10);

  sendCmd(ST7789_DISPON);
  delay(255);
}

void clearDisplay(uint16_t Color) {
  uint8_t i;
  uint8_t CL, CH;
  CL = (Color>>8);
  CH = Color;

  sendCmd(ST7789_CASET);
  sendData(0x00);
  sendData(0x00);
  sendData(SCR_WD >> 8);
  sendData(SCR_WD - 1);

  sendCmd(ST7789_RASET);
  sendData(0x00);
  sendData(0x00);
  sendData(SCR_HT >> 8);
  sendData(SCR_HT - 1);

  sendCmd(ST7789_RAMWR);

  for(int i=0; i<(SCR_WD * SCR_HT); i++) {
    sendData(CH);
    sendData(CL);
  }
}


void setup() {
  //Serial.begin (9600);
  initDisplay();
  clearDisplay(WHITE);
}

void loop(){}
  1. Подключить лог анализатор
  2. Срисовать коды инициализации адафрут библиотеки
  3. Запрграммировать аналогично
  4. Запустить свою программу и проверить что в дисплей падают правильные данные в правильной последовательности

Вот тут:

минимальный набор команд для запуска дисплея.
Попробуйте …
И не надо всё время дергать CS !!!

1 лайк

К сожалению логического анализатора нет. Библиотеки пытался распарсить, с одной стороны вроде последовательность инициализации такая же, с другой стороны в некоторых местах начинаются такие дебри абстракций, которые мой уровень пока разобрать не в состоянии. Вообще изучение библиотек это первое, с чего начал, недели две бьюсь, сейчас прошу помощи у тех, кто понимает суть предмета.

Спасибо за наводку!!!

Передергивание CS это как раз таки из одной из универсальных библиотек) По факту можно один раз выставить в 0.

Там для tiny код и SPI через ногодрыг - надо немного подкрутить …

Получить последовательность байт от любой библиотеки достаточно просто - надо в библиотеке SPI вставить вывод в консоль уровня DC и байта, который летит в SPDR !!!

1 лайк

Пока с nano работаю, использую hardware SPI, но на инициализацию дисплея из примера это вроде не должно влиять.

Вот за это прям гранд спасибо, не знал!

Вроде подправил под ваше соединение:

Спойлер
int const dc = 0;
int const mosi = 3;
int const sck = 5;
int const cs = 1;
 
// Classic ATtiny port manipulations - assumes all pins in same port
#define PORT_TOGGLE(x)  PINB = (x)
#define PORT_LOW(x)     PORTB = PORTB & ~((x));
#define PORT_HIGH(x)    PORTB = PORTB | ((x))
#define PORT_OUTPUT(x)  DDRB = (x)
 
// Display parameters - uncomment the line for the one you want to use
 
// Adafruit 1.44" 128x128 display
// int const xsize = 128, ysize = 128, xoff = 2, yoff = 1, invert = 0, rotate = 3, bgr = 1;
 
// AliExpress 1.44" 128x128 display
// int const xsize = 128, ysize = 128, xoff = 2, yoff = 1, invert = 0, rotate = 3, bgr = 1;
 
// Adafruit 0.96" 160x80 display
// int const xsize = 160, ysize = 80, xoff = 0, yoff = 24, invert = 0, rotate = 6, bgr = 0;
 
// AliExpress 0.96" 160x80 display
// int const xsize = 160, ysize = 80, xoff = 1, yoff = 26, invert = 1, rotate = 0, bgr = 1;
 
// Adafruit 1.8" 160x128 display
int const xsize = 128, ysize = 160, xoff = 2, yoff = 1, invert = 0, rotate = 5, bgr = 0;
 
// AliExpress 1.8" 160x128 display (red PCB)
// int const xsize = 160, ysize = 128, xoff = 0, yoff = 0, invert = 0, rotate = 0, bgr = 1;
 
// AliExpress 1.8" 160x128 display (blue PCB)
// int const xsize = 160, ysize = 128, xoff = 0, yoff = 0, invert = 0, rotate = 6, bgr = 0;
 
// Adafruit 1.14" 240x135 display
// int const xsize = 240, ysize = 135, xoff = 40, yoff = 53, invert = 1, rotate = 6, bgr = 0;
 
// AliExpress 1.14" 240x135 display
// int const xsize = 240, ysize = 135, xoff = 40, yoff = 52, invert = 1, rotate = 0, bgr = 0;
 
// Adafruit 1.3" 240x240 display
// int const xsize = 240, ysize = 240, xoff = 0, yoff = 80, invert = 1, rotate = 5, bgr = 0;
 
// Adafruit 1.54" 240x240 display
// int const xsize = 240, ysize = 240, xoff = 0, yoff = 80, invert = 1, rotate = 5, bgr = 0;
 
// AliExpress 1.54" 240x240 display
// int const xsize = 240, ysize = 240, xoff = 0, yoff = 80, invert = 1, rotate = 5, bgr = 0;
 
// Adafruit 1.9" 320x170 display
// int const xsize = 320, ysize = 170, xoff = 0, yoff = 35, invert = 1, rotate = 0, bgr = 0;
 
// AliExpress 1.9" 320x170 display
// int const xsize = 320, ysize = 170, xoff = 0, yoff = 35, invert = 1, rotate = 0, bgr = 0;
 
// Adafruit 1.47" 320x172 rounded rectangle display
// int const xsize = 320, ysize = 172, xoff = 0, yoff = 34, invert = 1, rotate = 0, bgr = 0;
 
// AliExpress 1.47" 320x172 rounded rectangle display
// int const xsize = 320, ysize = 172, xoff = 0, yoff = 34, invert = 1, rotate = 0, bgr = 0;
 
// Adafruit 2.0" 320x240 display
// int const xsize = 320, ysize = 240, xoff = 0, yoff = 0, invert = 1, rotate = 6, bgr = 0;
 
// AliExpress 2.0" 320x240 display
// int const xsize = 320, ysize = 240, xoff = 0, yoff = 0, invert = 1, rotate = 0, bgr = 0;
 
// Adafruit 2.2" 320x240 display
// int const xsize = 320, ysize = 240, xoff = 0, yoff = 0, invert = 0, rotate = 4, bgr = 1;
 
// AliExpress 2.4" 320x240 display
// int const xsize = 320, ysize = 240, xoff = 0, yoff = 0, invert = 0, rotate = 2, bgr = 1;
 
// Character set for text - stored in program memory
const uint8_t CharMap[96][6] PROGMEM = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 
{ 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00 }, 
{ 0x00, 0x07, 0x00, 0x07, 0x00, 0x00 }, 
{ 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00 }, 
{ 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00 }, 
{ 0x23, 0x13, 0x08, 0x64, 0x62, 0x00 }, 
{ 0x36, 0x49, 0x56, 0x20, 0x50, 0x00 }, 
{ 0x00, 0x08, 0x07, 0x03, 0x00, 0x00 }, 
{ 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00 }, 
{ 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00 }, 
{ 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00 }, 
{ 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00 }, 
{ 0x00, 0x80, 0x70, 0x30, 0x00, 0x00 }, 
{ 0x08, 0x08, 0x08, 0x08, 0x08, 0x00 }, 
{ 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, 
{ 0x20, 0x10, 0x08, 0x04, 0x02, 0x00 }, 
{ 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00 }, 
{ 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00 }, 
{ 0x72, 0x49, 0x49, 0x49, 0x46, 0x00 }, 
{ 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00 }, 
{ 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00 }, 
{ 0x27, 0x45, 0x45, 0x45, 0x39, 0x00 }, 
{ 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00 }, 
{ 0x41, 0x21, 0x11, 0x09, 0x07, 0x00 }, 
{ 0x36, 0x49, 0x49, 0x49, 0x36, 0x00 }, 
{ 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00 }, 
{ 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 }, 
{ 0x00, 0x40, 0x34, 0x00, 0x00, 0x00 }, 
{ 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, 
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x00 }, 
{ 0x00, 0x41, 0x22, 0x14, 0x08, 0x00 }, 
{ 0x02, 0x01, 0x59, 0x09, 0x06, 0x00 }, 
{ 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00 }, 
{ 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00 }, 
{ 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00 }, 
{ 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00 }, 
{ 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00 }, 
{ 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00 }, 
{ 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00 }, 
{ 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00 }, 
{ 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00 }, 
{ 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00 }, 
{ 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00 }, 
{ 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00 }, 
{ 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00 }, 
{ 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00 }, 
{ 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00 }, 
{ 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00 }, 
{ 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00 }, 
{ 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00 }, 
{ 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00 }, 
{ 0x26, 0x49, 0x49, 0x49, 0x32, 0x00 }, 
{ 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00 }, 
{ 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00 }, 
{ 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00 }, 
{ 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00 }, 
{ 0x63, 0x14, 0x08, 0x14, 0x63, 0x00 }, 
{ 0x03, 0x04, 0x78, 0x04, 0x03, 0x00 }, 
{ 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00 }, 
{ 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00 }, 
{ 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 }, 
{ 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00 }, 
{ 0x04, 0x02, 0x01, 0x02, 0x04, 0x00 }, 
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00 }, 
{ 0x00, 0x03, 0x07, 0x08, 0x00, 0x00 }, 
{ 0x20, 0x54, 0x54, 0x78, 0x40, 0x00 }, 
{ 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00 }, 
{ 0x38, 0x44, 0x44, 0x44, 0x28, 0x00 }, 
{ 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00 }, 
{ 0x38, 0x54, 0x54, 0x54, 0x18, 0x00 }, 
{ 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00 }, 
{ 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00 }, 
{ 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00 }, 
{ 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00 }, 
{ 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00 }, 
{ 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00 }, 
{ 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00 }, 
{ 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00 }, 
{ 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00 }, 
{ 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 }, 
{ 0xFC, 0x18, 0x24, 0x24, 0x18, 0x00 }, 
{ 0x18, 0x24, 0x24, 0x18, 0xFC, 0x00 }, 
{ 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00 }, 
{ 0x48, 0x54, 0x54, 0x54, 0x24, 0x00 }, 
{ 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00 }, 
{ 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00 }, 
{ 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00 }, 
{ 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00 }, 
{ 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 }, 
{ 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00 }, 
{ 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00 }, 
{ 0x00, 0x08, 0x36, 0x41, 0x00, 0x00 }, 
{ 0x00, 0x00, 0x77, 0x00, 0x00, 0x00 }, 
{ 0x00, 0x41, 0x36, 0x08, 0x00, 0x00 }, 
{ 0x00, 0x06, 0x09, 0x06, 0x00, 0x00 },  // degree symbol = '~'
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }
};
 
// TFT colour display **********************************************
 
int const CASET = 0x2A; // Define column address
int const RASET = 0x2B; // Define row address
int const RAMWR = 0x2C; // Write to display RAM
 
int const White = 0xFFFF;
int const Black = 0;
 
// Current plot position and colours
int xpos, ypos;
int fore = White;
int back = Black;
int scale = 1;     // Text scale
 
// Send a byte to the display
 
void Data (uint8_t d) {
  for (uint8_t bit = 0x80; bit; bit >>= 1) {
    PORT_TOGGLE(1<<sck);
    if (d & bit) PORT_HIGH(1<<mosi); else PORT_LOW(1<<mosi);
    PORT_TOGGLE(1<<sck);
  }
}
 
// Send a command to the display
void Command (uint8_t c) {
  PORT_TOGGLE(1<<dc);
  Data(c);
  PORT_TOGGLE(1<<dc);
}
 
// Send a command followed by two data words
void Command2 (uint8_t c, uint16_t d1, uint16_t d2) {
  PORT_TOGGLE(1<<dc);
  Data(c);
  PORT_TOGGLE(1<<dc);
  Data(d1>>8); Data(d1); Data(d2>>8); Data(d2);
}
  
void InitDisplay () {
  PORT_OUTPUT(1<<dc | 1<<cs | 1<<mosi | 1<<sck); // All outputs
  PORT_HIGH(1<<dc | 1<<cs);       // Outputs high
  PORT_TOGGLE(1<<cs);
  Command(0x01);                           // Software reset
  delay(250);                              // delay 250 ms
  Command(0x36); Data(rotate<<5 | bgr<<3); // Set orientation and rgb/bgr
  Command(0x3A); Data(0x05);               // Set color mode - 16-bit color
  Command(0x20+invert);                    // Invert
  Command(0x11);                           // Out of sleep mode
  delay(150);
  PORT_TOGGLE(1<<cs);
}
 
void DisplayOn () {
  PORT_TOGGLE(1<<cs);
  Command(0x29);                           // Display on
  delay(150);
  PORT_TOGGLE(1<<cs);
}
 
void ClearDisplay () {
  PORT_TOGGLE(1<<cs);
  Command2(CASET, yoff, yoff + ysize - 1);
  Command2(RASET, xoff, xoff + xsize - 1);
  //Command(0x3A); Data(0x03);               // 12-bit colour
  Command(RAMWR);                          // Leaves mosi low
  for (int i=0; i<xsize*4; i++) {
    for (int j=0; j<ysize*4; j++) {
    PORT_TOGGLE(1<<sck);
    PORT_TOGGLE(1<<sck);
    }
  }
  //Command(0x3A); Data(0x05);               // Back to 16-bit colour
  PORT_TOGGLE(1<<cs);
}
 
unsigned int Colour (int r, int g, int b) {
  return (r & 0xf8)<<8 | (g & 0xfc)<<3 | b>>3;
}
 
// Move current plot position to x,y
void MoveTo (int x, int y) {
  xpos = x; ypos = y;
}
 
// Plot point at x,y
void PlotPoint (int x, int y) {
  PORT_TOGGLE(1<<cs);
  Command2(CASET, yoff+y, yoff+y);
  Command2(RASET, xoff+x, xoff+x);
  Command(RAMWR); Data(fore>>8); Data(fore & 0xff);
  PORT_TOGGLE(1<<cs);
}
 
// Draw a line to x,y
void DrawTo (int x, int y) {
  int sx, sy, e2, err;
  int dx = abs(x - xpos);
  int dy = abs(y - ypos);
  if (xpos < x) sx = 1; else sx = -1;
  if (ypos < y) sy = 1; else sy = -1;
  err = dx - dy;
  for (;;) {
    PlotPoint(xpos, ypos);
    if (xpos==x && ypos==y) return;
    e2 = err<<1;
    if (e2 > -dy) { err = err - dy; xpos = xpos + sx; }
    if (e2 < dx) { err = err + dx; ypos = ypos + sy; }
  }
}
 
void FillRect (int w, int h) {
  PORT_TOGGLE(1<<cs);
  Command2(CASET, ypos+yoff, ypos+yoff+h-1);
  Command2(RASET, xpos+xoff, xpos+xoff+w-1);
  Command(RAMWR);
  uint8_t hi = fore>>8;
  uint8_t lo = fore & 0xff;
  for (int i=0; i<w; i++) {
    for (int j=0; j<h; j++) {
      Data(hi); Data(lo);
    }
  }
  PORT_TOGGLE(1<<cs);
}
 
void DrawRect (int w, int h) {
  int x1 = xpos, y1 = ypos;
  FillRect(w-1, 1); MoveTo(x1, y1+1);
  FillRect(1, h-1); MoveTo(x1+1, y1+h-1);
  FillRect(w-1, 1); MoveTo(x1+w-1, y1);
  FillRect(1, h-1);
  xpos = x1; ypos = y1;
}
 
void FillCircle (int radius) {
  int x1 = xpos, y1 = ypos, dx = 1, dy = 1;
  int x = radius - 1, y = 0;
  int err = dx - (radius<<1);
  while (x >= y) {
    MoveTo(x1-x, y1+y); FillRect(x<<1, 1);
    MoveTo(x1-y, y1+x); FillRect(y<<1, 1);
    MoveTo(x1-y, y1-x); FillRect(y<<1, 1);
    MoveTo(x1-x, y1-y); FillRect(x<<1, 1);
    if (err > 0) {
      x = x - 1; dx = dx + 2;
      err = err - (radius<<1) + dx;
    } else {
      y = y + 1; err = err + dy;
      dy = dy + 2;
    }
  }
  xpos = x1; ypos = y1;
}
 
void DrawCircle (int radius) {
  int x1 = xpos, y1 = ypos, dx = 1, dy = 1;
  int x = radius - 1, y = 0;
  int err = dx - (radius<<1);
  while (x >= y) {
    PlotPoint(x1-x, y1+y); PlotPoint(x1+x, y1+y);
    PlotPoint(x1-y, y1+x); PlotPoint(x1+y, y1+x);
    PlotPoint(x1-y, y1-x); PlotPoint(x1+y, y1-x);
    PlotPoint(x1-x, y1-y); PlotPoint(x1+x, y1-y);
    if (err > 0) {
      x = x - 1; dx = dx + 2;
      err = err - (radius<<1) + dx;
    } else {
      y = y + 1; err = err + dy;
      dy = dy + 2;
    }
  }
}
 
// Plot an ASCII character with bottom left corner at x,y
void PlotChar (char c) {
  int colour;
  PORT_TOGGLE(1<<cs);
  Command2(CASET, yoff+ypos, yoff+ypos+8*scale-1);
  Command2(RASET, xoff+xpos, xoff+xpos+6*scale-1);
  Command(RAMWR);
  for (int xx=0; xx<6; xx++) {
    int bits = pgm_read_byte(&CharMap[c-32][xx]);
    for (int xr=0; xr<scale; xr++) {
      for (int yy=0; yy<8; yy++) {
        if (bits>>(7-yy) & 1) colour = fore; else colour = back;
        for (int yr=0; yr<scale; yr++) {
          Data(colour>>8); Data(colour & 0xFF);
        }
      }
    }
  }
  PORT_TOGGLE(1<<cs);
  xpos = xpos + 6*scale;
}
 
// Plot text starting at the current plot position
void PlotText(PGM_P p) {
  while (1) {
    char c = pgm_read_byte(p++);
    if (c == 0) return;
    PlotChar(c);
  }
}
 
void PlotInt(int n) {
  bool lead = false;
  for (int d=10000; d>0; d = d/10) {
    char j = (n/d) % 10;
    if (j!=0 || lead || d==1) { PlotChar(j + '0'); lead = true; }
  }
}
 
void TestChart () {
  int sf=fore;
  fore = Colour(255, 0, 0);
  DrawRect(xsize, ysize);
  scale = 8;
  MoveTo((xsize-40)/2, (ysize-64)/2); PlotChar('F');
  scale = 1;
  fore=sf;
}
 
// Demos **********************************************
 
void BarChart () {
  int x0 = 0, y0 = 0, w = xsize, h = ysize, x1 = 15, y1 = 11;
  MoveTo(x0+(w-x1-90)/2+x1, y0+h-8); PlotText(PSTR("Sensor Readings"));
  // Horizontal axis
  int xinc = (w-x1)/20;
  MoveTo(x0+x1, y0+y1); DrawTo(x0+w-1, y0+y1);
  for (int i=0; i<=20; i=i+4) {
    int mark = x1+i*xinc;
    MoveTo(x0+mark, y0+y1); DrawTo(x0+mark, y0+y1-2);
    // Draw histogram
    if (i != 20) {
      int bar = xinc*4/3;
      for (int b=2; b>=0; b--) {
        fore = Colour(255, 127*b, 0); // Red, Orange, Yellow 
        MoveTo(x0+mark+bar*b-b+1, y0+y1+1); FillRect(bar, 5+random(h-y1-20));
      }
      fore = White;
    }
    if (i > 9) MoveTo(x0+mark-7, y0+y1-11); else MoveTo(x0+mark-3, y0+y1-11);
    PlotInt(i);
  }
  // Vertical axis
  int yinc = (h-y1)/20;
  MoveTo(x0+x1, y0+y1); DrawTo(x0+x1, y0+h-1);
  for (int i=0; i<=20; i=i+5) {
    int mark = y1+i*yinc;
    MoveTo(x0+x1, y0+mark); DrawTo(x0+x1-2, y0+mark);
    if (i > 9) MoveTo(x0+x1-15, y0+mark-4); else MoveTo(x0+x1-9, y0+mark-4);
    PlotInt(i);
  }
}
 
void Waterfall () {
  int x0 = 0, y0 = 0, w = xsize, h = ysize, x1 = 15, y1 = 11;
  int factor = 5160/h*10;
  MoveTo(x0+(w-x1-60)/2+x1, y0+h-8); PlotText(PSTR("Luminance"));
  // Horizontal axis
  int xinc = (w-x1-15)/30;
  MoveTo(x0+x1, y0+y1); DrawTo(x0+x1+xinc*20, y0+y1);
  for (int i=0; i<=20; i=i+5) {
    int mark = x1+i*xinc;
    MoveTo(x0+mark, y0+y1); DrawTo(x0+mark, y0+y1-2);
    if (i > 9) MoveTo(x0+mark-7, y0+y1-11); else MoveTo(x0+mark-3, y0+y1-11);
    PlotInt(i);
  }
  // Vertical axis
  int yinc = (h-y1)/20;
  MoveTo(x0+x1, y0+y1); DrawTo(x0+x1, y0+h-1);
  for (int i=0; i<=20; i=i+5) {
    int mark = y1+i*yinc;
    MoveTo(x0+x1, y0+mark); DrawTo(x0+x1-2, y0+mark);
    if (i > 9) MoveTo(x0+x1-15, y0+mark-4); else MoveTo(x0+x1-9, y0+mark-4);
    PlotInt(i);
  }
  // Diagonal axis
  yinc = xinc/2;
  // MoveTo(x0+x1, y0+y1); DrawTo(x0+x1+10*xinc, y0+y1+10*xinc);
  MoveTo(x0+x1+20*xinc, y0+y1); DrawTo(x0+x1+30*xinc, y0+y1+10*xinc);
  for (int i=0; i<=20; i=i+5) {
    MoveTo(x0+x1+20*xinc+i*xinc/2, y0+y1+i*xinc/2);
    DrawTo(x0+x1+20*xinc+i*xinc/2+3, y0+y1+i*xinc/2);
    MoveTo(x0+x1+20*xinc+i*xinc/2+6, y0+y1+i*xinc/2-4); PlotInt(i);
  }
  // Plot data
  for (int y=20; y>=0; y--) {
    for (int i=0; i<=20; i++) {
      int fn0 = 180-(i-10)*(i-10)-(y-10)*(y-10);
      int fn1 = 180-(i+1-10)*(i+1-10)-(y-10)*(y-10);
      fore = Colour(255, 255, 0);
      MoveTo(x0+x1+y*yinc+i*xinc, y0+y1+y*yinc+fn0*fn0/factor);
      DrawTo(x0+x1+y*yinc+(i+1)*xinc, y0+y1+y*yinc+fn1*fn1/factor);
      fore = White;
    }
  }
}
  
// Setup **********************************************
 
void setup() {
  InitDisplay();
  ClearDisplay();
  DisplayOn();
  MoveTo(0,0);
  TestChart();
}
 
void loop () {
  //BarChart();
  //Waterfall();
  for (;;);
}

Но тут SPI через ногодрыг !

У вас в коде digitalWrite - это СОВСЕМ не быстро !!!
Может быть только для Reset надо будет добавить

pinMode(rstPin, OUTPUT);
digitalWrite(rstPin, HIGH);
1 лайк

SetBit?

Типа как тут.

гранит науки он такой …

1 лайк

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

Может сначала с библиотеки запустить, а потом наслаждаться уже без?

Вещь годная, не поспоришь. Я светодиоды к ногам подключаю и визуально смотрю, мигают, мерцают или вообще не реагируют)))

Очень тяжелые они, многофункциональность благо и зло одновременно)

Да вы супермен :grinning: на частоте 400 кГц по светодиодам шину расшифровать.

1 лайк

Ну как, если слабо замерцал, значит данные идут, уже кое о чем говорит)))

Поправил под аппаратный SPI:

Спойлер
#include <SPI.h>
int const dc = 0;
int const mosi = 3;
int const sck = 5;
int const cs = 1;

// Classic ATtiny port manipulations - assumes all pins in same port
#define PORT_TOGGLE(x)  PINB = (x)
#define PORT_LOW(x)     PORTB = PORTB & ~((x));
#define PORT_HIGH(x)    PORTB = PORTB | ((x))
#define PORT_OUTPUT(x)  DDRB = (x)

// Display parameters - uncomment the line for the one you want to use

// Adafruit 1.44" 128x128 display
// int const xsize = 128, ysize = 128, xoff = 2, yoff = 1, invert = 0, rotate = 3, bgr = 1;

// AliExpress 1.44" 128x128 display
// int const xsize = 128, ysize = 128, xoff = 2, yoff = 1, invert = 0, rotate = 3, bgr = 1;

// Adafruit 0.96" 160x80 display
// int const xsize = 160, ysize = 80, xoff = 0, yoff = 24, invert = 0, rotate = 6, bgr = 0;

// AliExpress 0.96" 160x80 display
// int const xsize = 160, ysize = 80, xoff = 1, yoff = 26, invert = 1, rotate = 0, bgr = 1;

// Adafruit 1.8" 160x128 display
int const xsize = 128, ysize = 160, xoff = 2, yoff = 1, invert = 0, rotate = 5, bgr = 0;

// AliExpress 1.8" 160x128 display (red PCB)
// int const xsize = 160, ysize = 128, xoff = 0, yoff = 0, invert = 0, rotate = 0, bgr = 1;

// AliExpress 1.8" 160x128 display (blue PCB)
// int const xsize = 160, ysize = 128, xoff = 0, yoff = 0, invert = 0, rotate = 6, bgr = 0;

// Adafruit 1.14" 240x135 display
// int const xsize = 240, ysize = 135, xoff = 40, yoff = 53, invert = 1, rotate = 6, bgr = 0;

// AliExpress 1.14" 240x135 display
// int const xsize = 240, ysize = 135, xoff = 40, yoff = 52, invert = 1, rotate = 0, bgr = 0;

// Adafruit 1.3" 240x240 display
// int const xsize = 240, ysize = 240, xoff = 0, yoff = 80, invert = 1, rotate = 5, bgr = 0;

// Adafruit 1.54" 240x240 display
// int const xsize = 240, ysize = 240, xoff = 0, yoff = 80, invert = 1, rotate = 5, bgr = 0;

// AliExpress 1.54" 240x240 display
// int const xsize = 240, ysize = 240, xoff = 0, yoff = 80, invert = 1, rotate = 5, bgr = 0;

// Adafruit 1.9" 320x170 display
// int const xsize = 320, ysize = 170, xoff = 0, yoff = 35, invert = 1, rotate = 0, bgr = 0;

// AliExpress 1.9" 320x170 display
// int const xsize = 320, ysize = 170, xoff = 0, yoff = 35, invert = 1, rotate = 0, bgr = 0;

// Adafruit 1.47" 320x172 rounded rectangle display
// int const xsize = 320, ysize = 172, xoff = 0, yoff = 34, invert = 1, rotate = 0, bgr = 0;

// AliExpress 1.47" 320x172 rounded rectangle display
// int const xsize = 320, ysize = 172, xoff = 0, yoff = 34, invert = 1, rotate = 0, bgr = 0;

// Adafruit 2.0" 320x240 display
// int const xsize = 320, ysize = 240, xoff = 0, yoff = 0, invert = 1, rotate = 6, bgr = 0;

// AliExpress 2.0" 320x240 display
// int const xsize = 320, ysize = 240, xoff = 0, yoff = 0, invert = 1, rotate = 0, bgr = 0;

// Adafruit 2.2" 320x240 display
// int const xsize = 320, ysize = 240, xoff = 0, yoff = 0, invert = 0, rotate = 4, bgr = 1;

// AliExpress 2.4" 320x240 display
// int const xsize = 320, ysize = 240, xoff = 0, yoff = 0, invert = 0, rotate = 2, bgr = 1;

// Character set for text - stored in program memory
const uint8_t CharMap[96][6] PROGMEM = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
    { 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00 },
    { 0x00, 0x07, 0x00, 0x07, 0x00, 0x00 },
    { 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00 },
    { 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00 },
    { 0x23, 0x13, 0x08, 0x64, 0x62, 0x00 },
    { 0x36, 0x49, 0x56, 0x20, 0x50, 0x00 },
    { 0x00, 0x08, 0x07, 0x03, 0x00, 0x00 },
    { 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00 },
    { 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00 },
    { 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00 },
    { 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00 },
    { 0x00, 0x80, 0x70, 0x30, 0x00, 0x00 },
    { 0x08, 0x08, 0x08, 0x08, 0x08, 0x00 },
    { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },
    { 0x20, 0x10, 0x08, 0x04, 0x02, 0x00 },
    { 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00 },
    { 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00 },
    { 0x72, 0x49, 0x49, 0x49, 0x46, 0x00 },
    { 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00 },
    { 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00 },
    { 0x27, 0x45, 0x45, 0x45, 0x39, 0x00 },
    { 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00 },
    { 0x41, 0x21, 0x11, 0x09, 0x07, 0x00 },
    { 0x36, 0x49, 0x49, 0x49, 0x36, 0x00 },
    { 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00 },
    { 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 },
    { 0x00, 0x40, 0x34, 0x00, 0x00, 0x00 },
    { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 },
    { 0x14, 0x14, 0x14, 0x14, 0x14, 0x00 },
    { 0x00, 0x41, 0x22, 0x14, 0x08, 0x00 },
    { 0x02, 0x01, 0x59, 0x09, 0x06, 0x00 },
    { 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00 },
    { 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00 },
    { 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00 },
    { 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00 },
    { 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00 },
    { 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00 },
    { 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00 },
    { 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00 },
    { 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00 },
    { 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00 },
    { 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00 },
    { 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00 },
    { 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00 },
    { 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00 },
    { 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00 },
    { 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00 },
    { 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00 },
    { 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00 },
    { 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00 },
    { 0x26, 0x49, 0x49, 0x49, 0x32, 0x00 },
    { 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00 },
    { 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00 },
    { 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00 },
    { 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00 },
    { 0x63, 0x14, 0x08, 0x14, 0x63, 0x00 },
    { 0x03, 0x04, 0x78, 0x04, 0x03, 0x00 },
    { 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00 },
    { 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00 },
    { 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 },
    { 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00 },
    { 0x04, 0x02, 0x01, 0x02, 0x04, 0x00 },
    { 0x40, 0x40, 0x40, 0x40, 0x40, 0x00 },
    { 0x00, 0x03, 0x07, 0x08, 0x00, 0x00 },
    { 0x20, 0x54, 0x54, 0x78, 0x40, 0x00 },
    { 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00 },
    { 0x38, 0x44, 0x44, 0x44, 0x28, 0x00 },
    { 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00 },
    { 0x38, 0x54, 0x54, 0x54, 0x18, 0x00 },
    { 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00 },
    { 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00 },
    { 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00 },
    { 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00 },
    { 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00 },
    { 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00 },
    { 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00 },
    { 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00 },
    { 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00 },
    { 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 },
    { 0xFC, 0x18, 0x24, 0x24, 0x18, 0x00 },
    { 0x18, 0x24, 0x24, 0x18, 0xFC, 0x00 },
    { 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00 },
    { 0x48, 0x54, 0x54, 0x54, 0x24, 0x00 },
    { 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00 },
    { 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00 },
    { 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00 },
    { 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00 },
    { 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 },
    { 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00 },
    { 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00 },
    { 0x00, 0x08, 0x36, 0x41, 0x00, 0x00 },
    { 0x00, 0x00, 0x77, 0x00, 0x00, 0x00 },
    { 0x00, 0x41, 0x36, 0x08, 0x00, 0x00 },
    { 0x00, 0x06, 0x09, 0x06, 0x00, 0x00 },  // degree symbol = '~'
    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }
};

// TFT colour display **********************************************

int const CASET = 0x2A; // Define column address
int const RASET = 0x2B; // Define row address
int const RAMWR = 0x2C; // Write to display RAM

int const White = 0xFFFF;
int const Black = 0;

// Current plot position and colours
int xpos, ypos;
int fore = White;
int back = Black;
int scale = 1;     // Text scale

// Send a byte to the display

void Data (uint8_t d) {
    SPI.transfer(d);
    
//    for (uint8_t bit = 0x80; bit; bit >>= 1) {
//        PORT_TOGGLE(1 << sck);
//        if (d & bit) PORT_HIGH(1 << mosi); else PORT_LOW(1 << mosi);
//        PORT_TOGGLE(1 << sck);
//    }
}

// Send a command to the display
void Command (uint8_t c) {
    PORT_TOGGLE(1 << dc);
    Data(c);
    PORT_TOGGLE(1 << dc);
}

// Send a command followed by two data words
void Command2 (uint8_t c, uint16_t d1, uint16_t d2) {
    PORT_TOGGLE(1 << dc);
    Data(c);
    PORT_TOGGLE(1 << dc);
    Data(d1 >> 8); Data(d1); Data(d2 >> 8); Data(d2);
}

void InitDisplay () {
    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV2);
    PORT_OUTPUT(1 << dc | 1 << cs | 1 << mosi | 1 << sck); // All outputs
    PORT_HIGH(1 << dc | 1 << cs);   // Outputs high
    PORT_TOGGLE(1 << cs);
    Command(0x01);                           // Software reset
    delay(250);                              // delay 250 ms
    Command(0x36); Data(rotate << 5 | bgr << 3); // Set orientation and rgb/bgr
    Command(0x3A); Data(0x05);               // Set color mode - 16-bit color
    Command(0x20 + invert);                  // Invert
    Command(0x11);                           // Out of sleep mode
    delay(150);
    PORT_TOGGLE(1 << cs);
}

void DisplayOn () {
    PORT_TOGGLE(1 << cs);
    Command(0x29);                           // Display on
    delay(150);
    PORT_TOGGLE(1 << cs);
}

void ClearDisplay () {
    PORT_TOGGLE(1 << cs);
    Command2(CASET, yoff, yoff + ysize - 1);
    Command2(RASET, xoff, xoff + xsize - 1);
    //Command(0x3A); Data(0x03);               // 12-bit colour
    Command(RAMWR);                          // Leaves mosi low
    for (long i = 0; i < xsize * ysize; i++) {
        SPI.transfer(0);
        SPI.transfer(0);
    };
//    for (int i = 0; i < xsize * 4; i++) {
//        for (int j = 0; j < ysize * 4; j++) {
//            PORT_TOGGLE(1 << sck);
//            PORT_TOGGLE(1 << sck);
//        }
//    }
    //Command(0x3A); Data(0x05);               // Back to 16-bit colour
    PORT_TOGGLE(1 << cs);
}

unsigned int Colour (int r, int g, int b) {
    return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3;
}

// Move current plot position to x,y
void MoveTo (int x, int y) {
    xpos = x; ypos = y;
}

// Plot point at x,y
void PlotPoint (int x, int y) {
    PORT_TOGGLE(1 << cs);
    Command2(CASET, yoff + y, yoff + y);
    Command2(RASET, xoff + x, xoff + x);
    Command(RAMWR); Data(fore >> 8); Data(fore & 0xff);
    PORT_TOGGLE(1 << cs);
}

// Draw a line to x,y
void DrawTo (int x, int y) {
    int sx, sy, e2, err;
    int dx = abs(x - xpos);
    int dy = abs(y - ypos);
    if (xpos < x) sx = 1; else sx = -1;
    if (ypos < y) sy = 1; else sy = -1;
    err = dx - dy;
    for (;;) {
        PlotPoint(xpos, ypos);
        if (xpos == x && ypos == y) return;
        e2 = err << 1;
        if (e2 > -dy) {
            err = err - dy;
            xpos = xpos + sx;
        }
        if (e2 < dx) {
            err = err + dx;
            ypos = ypos + sy;
        }
    }
}

void FillRect (int w, int h) {
    PORT_TOGGLE(1 << cs);
    Command2(CASET, ypos + yoff, ypos + yoff + h - 1);
    Command2(RASET, xpos + xoff, xpos + xoff + w - 1);
    Command(RAMWR);
    uint8_t hi = fore >> 8;
    uint8_t lo = fore & 0xff;
    for (int i = 0; i < w; i++) {
        for (int j = 0; j < h; j++) {
            Data(hi); Data(lo);
        }
    }
    PORT_TOGGLE(1 << cs);
}

void DrawRect (int w, int h) {
    int x1 = xpos, y1 = ypos;
    FillRect(w - 1, 1); MoveTo(x1, y1 + 1);
    FillRect(1, h - 1); MoveTo(x1 + 1, y1 + h - 1);
    FillRect(w - 1, 1); MoveTo(x1 + w - 1, y1);
    FillRect(1, h - 1);
    xpos = x1; ypos = y1;
}

void FillCircle (int radius) {
    int x1 = xpos, y1 = ypos, dx = 1, dy = 1;
    int x = radius - 1, y = 0;
    int err = dx - (radius << 1);
    while (x >= y) {
        MoveTo(x1 - x, y1 + y); FillRect(x << 1, 1);
        MoveTo(x1 - y, y1 + x); FillRect(y << 1, 1);
        MoveTo(x1 - y, y1 - x); FillRect(y << 1, 1);
        MoveTo(x1 - x, y1 - y); FillRect(x << 1, 1);
        if (err > 0) {
            x = x - 1; dx = dx + 2;
            err = err - (radius << 1) + dx;
        } else {
            y = y + 1; err = err + dy;
            dy = dy + 2;
        }
    }
    xpos = x1; ypos = y1;
}

void DrawCircle (int radius) {
    int x1 = xpos, y1 = ypos, dx = 1, dy = 1;
    int x = radius - 1, y = 0;
    int err = dx - (radius << 1);
    while (x >= y) {
        PlotPoint(x1 - x, y1 + y); PlotPoint(x1 + x, y1 + y);
        PlotPoint(x1 - y, y1 + x); PlotPoint(x1 + y, y1 + x);
        PlotPoint(x1 - y, y1 - x); PlotPoint(x1 + y, y1 - x);
        PlotPoint(x1 - x, y1 - y); PlotPoint(x1 + x, y1 - y);
        if (err > 0) {
            x = x - 1; dx = dx + 2;
            err = err - (radius << 1) + dx;
        } else {
            y = y + 1; err = err + dy;
            dy = dy + 2;
        }
    }
}

// Plot an ASCII character with bottom left corner at x,y
void PlotChar (char c) {
    int colour;
    PORT_TOGGLE(1 << cs);
    Command2(CASET, yoff + ypos, yoff + ypos + 8 * scale - 1);
    Command2(RASET, xoff + xpos, xoff + xpos + 6 * scale - 1);
    Command(RAMWR);
    for (int xx = 0; xx < 6; xx++) {
        int bits = pgm_read_byte(&CharMap[c - 32][xx]);
        for (int xr = 0; xr < scale; xr++) {
            for (int yy = 0; yy < 8; yy++) {
                if (bits >> (7 - yy) & 1) colour = fore; else colour = back;
                for (int yr = 0; yr < scale; yr++) {
                    Data(colour >> 8); Data(colour & 0xFF);
                }
            }
        }
    }
    PORT_TOGGLE(1 << cs);
    xpos = xpos + 6 * scale;
}

// Plot text starting at the current plot position
void PlotText(PGM_P p) {
    while (1) {
        char c = pgm_read_byte(p++);
        if (c == 0) return;
        PlotChar(c);
    }
}

void PlotInt(int n) {
    bool lead = false;
    for (int d = 10000; d > 0; d = d / 10) {
        char j = (n / d) % 10;
        if (j != 0 || lead || d == 1) {
            PlotChar(j + '0');
            lead = true;
        }
    }
}

void TestChart () {
    int sf = fore;
    fore = Colour(255, 0, 0);
    DrawRect(xsize, ysize);
    scale = 8;
    MoveTo((xsize - 40) / 2, (ysize - 64) / 2); PlotChar('F');
    scale = 1;
    fore = sf;
}

// Demos **********************************************

void BarChart () {
    int x0 = 0, y0 = 0, w = xsize, h = ysize, x1 = 15, y1 = 11;
    MoveTo(x0 + (w - x1 - 90) / 2 + x1, y0 + h - 8); PlotText(PSTR("Sensor Readings"));
    // Horizontal axis
    int xinc = (w - x1) / 20;
    MoveTo(x0 + x1, y0 + y1); DrawTo(x0 + w - 1, y0 + y1);
    for (int i = 0; i <= 20; i = i + 4) {
        int mark = x1 + i * xinc;
        MoveTo(x0 + mark, y0 + y1); DrawTo(x0 + mark, y0 + y1 - 2);
        // Draw histogram
        if (i != 20) {
            int bar = xinc * 4 / 3;
            for (int b = 2; b >= 0; b--) {
                fore = Colour(255, 127 * b, 0); // Red, Orange, Yellow
                MoveTo(x0 + mark + bar * b - b + 1, y0 + y1 + 1); FillRect(bar, 5 + random(h - y1 - 20));
            }
            fore = White;
        }
        if (i > 9) MoveTo(x0 + mark - 7, y0 + y1 - 11); else MoveTo(x0 + mark - 3, y0 + y1 - 11);
        PlotInt(i);
    }
    // Vertical axis
    int yinc = (h - y1) / 20;
    MoveTo(x0 + x1, y0 + y1); DrawTo(x0 + x1, y0 + h - 1);
    for (int i = 0; i <= 20; i = i + 5) {
        int mark = y1 + i * yinc;
        MoveTo(x0 + x1, y0 + mark); DrawTo(x0 + x1 - 2, y0 + mark);
        if (i > 9) MoveTo(x0 + x1 - 15, y0 + mark - 4); else MoveTo(x0 + x1 - 9, y0 + mark - 4);
        PlotInt(i);
    }
}

void Waterfall () {
    int x0 = 0, y0 = 0, w = xsize, h = ysize, x1 = 15, y1 = 11;
    int factor = 5160 / h * 10;
    MoveTo(x0 + (w - x1 - 60) / 2 + x1, y0 + h - 8); PlotText(PSTR("Luminance"));
    // Horizontal axis
    int xinc = (w - x1 - 15) / 30;
    MoveTo(x0 + x1, y0 + y1); DrawTo(x0 + x1 + xinc * 20, y0 + y1);
    for (int i = 0; i <= 20; i = i + 5) {
        int mark = x1 + i * xinc;
        MoveTo(x0 + mark, y0 + y1); DrawTo(x0 + mark, y0 + y1 - 2);
        if (i > 9) MoveTo(x0 + mark - 7, y0 + y1 - 11); else MoveTo(x0 + mark - 3, y0 + y1 - 11);
        PlotInt(i);
    }
    // Vertical axis
    int yinc = (h - y1) / 20;
    MoveTo(x0 + x1, y0 + y1); DrawTo(x0 + x1, y0 + h - 1);
    for (int i = 0; i <= 20; i = i + 5) {
        int mark = y1 + i * yinc;
        MoveTo(x0 + x1, y0 + mark); DrawTo(x0 + x1 - 2, y0 + mark);
        if (i > 9) MoveTo(x0 + x1 - 15, y0 + mark - 4); else MoveTo(x0 + x1 - 9, y0 + mark - 4);
        PlotInt(i);
    }
    // Diagonal axis
    yinc = xinc / 2;
    // MoveTo(x0+x1, y0+y1); DrawTo(x0+x1+10*xinc, y0+y1+10*xinc);
    MoveTo(x0 + x1 + 20 * xinc, y0 + y1); DrawTo(x0 + x1 + 30 * xinc, y0 + y1 + 10 * xinc);
    for (int i = 0; i <= 20; i = i + 5) {
        MoveTo(x0 + x1 + 20 * xinc + i * xinc / 2, y0 + y1 + i * xinc / 2);
        DrawTo(x0 + x1 + 20 * xinc + i * xinc / 2 + 3, y0 + y1 + i * xinc / 2);
        MoveTo(x0 + x1 + 20 * xinc + i * xinc / 2 + 6, y0 + y1 + i * xinc / 2 - 4); PlotInt(i);
    }
    // Plot data
    for (int y = 20; y >= 0; y--) {
        for (int i = 0; i <= 20; i++) {
            int fn0 = 180 - (i - 10) * (i - 10) - (y - 10) * (y - 10);
            int fn1 = 180 - (i + 1 - 10) * (i + 1 - 10) - (y - 10) * (y - 10);
            fore = Colour(255, 255, 0);
            MoveTo(x0 + x1 + y * yinc + i * xinc, y0 + y1 + y * yinc + fn0 * fn0 / factor);
            DrawTo(x0 + x1 + y * yinc + (i + 1)*xinc, y0 + y1 + y * yinc + fn1 * fn1 / factor);
            fore = White;
        }
    }
}

// Setup **********************************************

void setup() {
    InitDisplay();
    ClearDisplay();
    DisplayOn();
    MoveTo(0, 0);
    TestChart();
}

void loop () {
    BarChart();
    Waterfall();
    for (;;);
}

1 лайк