diff --git a/ESPNTUhrPx.ino b/ESPNTUhrPx.ino index 336ffdb..1424e4b 100644 --- a/ESPNTUhrPx.ino +++ b/ESPNTUhrPx.ino @@ -1,4 +1,13 @@ -#define VERSION (char *) "V2.11" +#define VERSION (char *) "V2.17" + +/* + V2.12 230205 neues SDK 8266; AP+Wifi Client; lokaleip eingebaut + V2.13 230206 Datum/Uhrzeit zeit auch KW an + V2.14 230208 AP+STA nur wenn Wifi verbunden ist sonst geht der AP nicht + V2.15 230212 Verbesserung AP_STA modus;Wlan auf 1 Connect beschränkt; + V2.16 230212 MaxConnect auf 2; Beacon auf 250ms + V2.17 230227 alle unbekannten Seiten Leiten auf die IP um +*/ // Pins for LED MATRIX #include @@ -10,7 +19,7 @@ #define P_D 0 //#define P_E 0 #define P_OE 2 - #define PxMATRIX_COLOR_DEPTH 3 // This is how many color levels the display shows - the more the slower the update + #define PxMATRIX_COLOR_DEPTH 2 // This is how many color levels the display shows - the more the slower the update #define double_buffer // Creates a second buffer for backround drawing (doubles the required RAM) #define MATRIX_WIDTH 64 #define MATRIX_HEIGHT 32 @@ -33,10 +42,25 @@ IPAddress ip_local(192, 168, 13, 1); IPAddress ip_gateway(192, 168, 13, 1); IPAddress ip_subnet(255, 255, 255, 0); + char localip[16]; boolean APEnabled = false; char ssid[30] = "THW Freifunk"; char pass[30] = ""; char appass[30] = "gibteskeins"; + + String toStringIp(IPAddress ip) { + String res = ""; + for (int i = 0; i < 3; i++) { + res += String((ip >> (8 * i)) & 0xFF) + "."; + } + res += String(((ip >> 8 * 3)) & 0xFF); + return res; + } + + void html_handle_notsuccess(AsyncWebServerRequest *request); + void html_handle_notsuccess(AsyncWebServerRequest *request){ + request->send(200, "text/html", String("zur Konfigurationsseite")); + } //permanenter Speicher #include @@ -119,10 +143,10 @@ void LineV(uint8_t x, uint8_t y, uint8_t z, uint8_t red, uint8_t green, uint8_t } //eigene Schriften -#include "D:\arduino\Projekte\_includes\char3x5.h" -#include "D:\arduino\Projekte\_includes\char5x7.h" -#include "D:\arduino\Projekte\_includes\char6x8.h" -#include "D:\arduino\Projekte\_includes\char10x16.h" +#include +#include +#include +#include void doClearLEDsSeconds(int8_t ycorrection=0){ @@ -344,12 +368,6 @@ void drawSeconds(time_t t,int8_t ycorrection=0){ void showTimeTactical(time_t t){ uint16_t tmp = 0; - uint8_t x = 0; - uint8_t y = 0; - - uint8_t r = timeColor[0]; - uint8_t g = timeColor[1]; - uint8_t b = timeColor[2]; tmp = minute(t); if(lastminutes != tmp){ @@ -393,7 +411,7 @@ void drawDate(time_t t){ uint8_t g = dateColor[1]; uint8_t b = dateColor[2]; uint8_t x = 2; - uint8_t y = 3; + uint8_t y = 0; UnixTime stamp(0); stamp.getDateTime(t); @@ -455,9 +473,17 @@ void drawDate(time_t t){ void showDateTime(time_t t){ doClearLEDs(); drawDate(t); - drawTime(t); + drawTime(t,-6); if(withSeconds) - drawSeconds(t); + drawSeconds(t,-6); + uint8_t kw = GetWeekNumber(year(t),month(t),day(t)); + char str[6]; + char kws[3]; + itoa(kw,kws,10); + strcpy(str, "KW "); + strcat(str, kws); + + show3x5(0,26,str,kwColor[0],kwColor[1],kwColor[2]); } uint8_t clock_center_x = 16; @@ -723,6 +749,9 @@ void setup() { strcpy(APName, "NTUhr VPx "); strcat(APName, ChipID); + + WiFi.persistent(false); + WiFi.mode(WIFI_AP_STA); WiFi.begin(ssid,pass); WiFi.hostname(NetName); int xc = 0; @@ -733,7 +762,6 @@ void setup() { display_doupdate(); } if (WiFi.status() == WL_CONNECTED) { - char localip[16]; char str[5]; IPAddress lip; lip = WiFi.localIP(); @@ -764,14 +792,11 @@ void setup() { if(timenow > SECS_YR_2000){ timenow += 1; int Year; - byte Month, Day, Hour, Minute, Second; + byte Month, Day, Hour; setTime(timenow); Year = year(timenow); - Month = month(timenow); Day = day(timenow); Hour = hour(timenow); - Minute = minute(timenow); - Second = second(timenow); if(isDayLight(Hour,Day,weekday(),Month)) timenow += (SECS_PER_HOUR * 2); else @@ -793,18 +818,19 @@ void setup() { display_doupdate(); alwaysAccessPoint = true; } - if(alwaysAccessPoint){ - WiFi.disconnect(); - delay(1000); - ESP.eraseConfig(); - delay(1000); - WiFi.mode(WIFI_OFF); - WiFi.mode(WIFI_AP); - delay(1000); + if (WiFi.status() != WL_CONNECTED) { + WiFi.disconnect(); + delay(100); + WiFi.mode(WIFI_OFF); + delay(100); + WiFi.mode(WIFI_AP); + } + + delay(100); WiFi.softAPConfig(ip_local, ip_gateway, ip_subnet); //appass = ; - APEnabled = WiFi.softAP(APName, appass,2,0,1); + APEnabled = WiFi.softAP(APName, appass,2,0,2,250); if(!APEnabled) display.drawPixelRGB888(3,0,255,0,0); else @@ -818,17 +844,19 @@ void setup() { display_doupdate(); //für die automatische Umleitung - webServer.on("/generate_204", HTTP_GET, [](AsyncWebServerRequest *request){html_redirect(request);}); //Android captive portal. - webServer.on("/fwlink", HTTP_GET, [](AsyncWebServerRequest *request){html_redirect(request);}); //Microsoft captive portal. - webServer.on("/connecttest.txt", HTTP_GET, [](AsyncWebServerRequest *request){html_redirect(request);}); //www.msftconnecttest.com - webServer.on("/hotspot-detect.html", HTTP_GET, [](AsyncWebServerRequest *request){html_redirect(request);}); //captive.apple.com + /*webServer.on("/generate_204", HTTP_GET, [](AsyncWebServerRequest *request){html_root(request);}); //Android captive portal. + webServer.on("/fwlink", HTTP_GET, [](AsyncWebServerRequest *request){html_root(request);}); //Microsoft captive portal. + webServer.on("/connecttest.txt", HTTP_GET, [](AsyncWebServerRequest *request){html_root(request);}); //www.msftconnecttest.com + webServer.on("/hotspot-detect.html", HTTP_GET, [](AsyncWebServerRequest *request){html_root(request);}); //captive.apple.com webServer.on("/success.txt", HTTP_GET, [](AsyncWebServerRequest *request){html_handle_success(request);}); //detectportal.firefox.com/sucess.txt - webServer.onNotFound([](AsyncWebServerRequest *request){html_redirect(request);}); + webServer.on("/redirect", HTTP_GET, [](AsyncWebServerRequest *request){html_root(request);}); //Microsoft captive portal.*/ + webServer.onNotFound([](AsyncWebServerRequest *request){html_handle_notsuccess(request);}); //eigene Seiten webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){html_root(request);}); webServer.on("/do", HTTP_GET, [] (AsyncWebServerRequest *request) {html_do(request);}); webServer.on("/poll", HTTP_GET, [] (AsyncWebServerRequest *request) {html_poll(request);}); + //webServer.on("/resetAP", HTTP_GET, [] (AsyncWebServerRequest *request) {html_resetAP(request);}); AsyncElegantOTA.begin(&webServer); // Start AsyncElegantOTA webServer.begin(); @@ -856,7 +884,7 @@ void loop(){ Minute = minute(currentUNIXTime); Second = second(currentUNIXTime); WDay = weekday(); - if((isDayLight(Hour,Day,WDay,Month) != iDL) && ((Month == 10 & Hour >= 3) | (Month == 3))){ + if((isDayLight(Hour,Day,WDay,Month) != iDL) && (((Month == 10) & (Hour >= 3)) | (Month == 3))){ if(iDL){ doSetTime(currentUNIXTime - SECS_PER_HOUR); }else{ @@ -887,6 +915,7 @@ void loop(){ showAnalogTime(currentUNIXTime); showAnalogDate(currentUNIXTime); break; + } display_doupdate(); @@ -1091,12 +1120,22 @@ void html_do(AsyncWebServerRequest *request) { request->send(200, "text/plain", "NOK"); } +void html_resetAP(AsyncWebServerRequest *request) { + String s_value = ""; + s_value.toCharArray(appass, 30); + EEPROM.put(151,appass); + EEPROM.commit(); + request->send(200, "text/plain", "OK"); +} + // Replaces placeholder with button section in your web page char * html_processor(const String& var){ if(var == "VERSION"){ return VERSION; }else if(var == "ID"){ return ChipID; + }else if(var == "LOCALIP"){ + return localip; } return (char *) "not defined"; } @@ -1108,23 +1147,4 @@ String toggleState(int toggle){ break; } return ""; -} - -String toStringIp(IPAddress ip) { - String res = ""; - for (int i = 0; i < 3; i++) { - res += String((ip >> (8 * i)) & 0xFF) + "."; - } - res += String(((ip >> 8 * 3)) & 0xFF); - return res; -} - -void html_redirect(AsyncWebServerRequest *request){ - AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. - response->addHeader("Location", String("http://") + toStringIp(ip_local)); - request->send(response); -} - -void html_handle_success(AsyncWebServerRequest *request){ - request->send(200, "text/plain", "success"); -} +} \ No newline at end of file diff --git a/PxMatrix.h b/PxMatrix.h deleted file mode 100644 index 4b1e561..0000000 --- a/PxMatrix.h +++ /dev/null @@ -1,1500 +0,0 @@ -/********************************************************************* -This is a library for Chinese LED matrix displays - -Written by Dominic Buchstaller. -BSD license, check license.txt for more information -*********************************************************************/ - - -#ifndef _PxMATRIX_H -#define _PxMATRIX_H - -// Color depth per primary color - the more the slower the update -#ifndef PxMATRIX_COLOR_DEPTH - #define PxMATRIX_COLOR_DEPTH 4 -#endif - -#if PxMATRIX_COLOR_DEPTH > 8 || PxMATRIX_COLOR_DEPTH < 1 - #error "PxMATRIX_COLOR_DEPTH must be 1 to 8 bits maximum" -#endif - -// Defines how long we display things by default -#ifndef PxMATRIX_DEFAULT_SHOWTIME - #define PxMATRIX_DEFAULT_SHOWTIME 30 -#endif - -// Defines the speed of the SPI bus (reducing this may help if you experience noisy images) -#ifndef PxMATRIX_SPI_FREQUENCY -#define PxMATRIX_SPI_FREQUENCY 20000000 -#endif - -// Legacy suppport -#ifdef double_buffer -#define PxMATRIX_DOUBLE_BUFFER true -#endif - -#ifndef _BV -#define _BV(x) (1 << (x)) -#endif - -#if defined(ESP8266) || defined(ESP32) - #define SPI_TRANSFER(x,y) SPI.writeBytes(x,y) - #define SPI_BYTE(x) SPI.write(x) - #define SPI_2BYTE(x) SPI.write16(x) -#endif - -#ifdef __AVR__ - #define SPI_TRANSFER(x,y) SPI.transfer(x,y) - #define SPI_BYTE(x) SPI.transfer(x) - #define SPI_2BYTE(x) SPI.transfer16(x) -#endif - -#include "Adafruit_GFX.h" -#include "Arduino.h" -#include - -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - -#ifdef __AVR__ - #include -#endif - - - -#include - -// Sometimes some extra width needs to be passed to Adafruit GFX constructor -// to render text close to the end of the display correctly -#ifndef ADAFRUIT_GFX_EXTRA - #define ADAFRUIT_GFX_EXTRA 0 -#endif - - - -#ifdef ESP8266 - #define GPIO_REG_SET(val) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS,val) - #define GPIO_REG_CLEAR(val) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS,val) -#endif -#ifdef ESP32 - #define GPIO_REG_SET(val) GPIO.out_w1ts = val - #define GPIO_REG_CLEAR(val) GPIO.out_w1tc = val -#endif -#ifdef __AVR__ - #define GPIO_REG_SET(val) (val < 8) ? PORTD |= _BV(val) : PORTB |= _BV(val-8) - #define GPIO_REG_CLEAR(val) (val < 8) ? PORTD &= ~_BV(val) : PORTB &= ~_BV(val-8) -#endif - -#ifdef ESP32 - - #include "soc/spi_struct.h" - #include "esp32-hal-gpio.h" - - struct spi_struct_t { - spi_dev_t * dev; - #if !CONFIG_DISABLE_HAL_LOCKS - xSemaphoreHandle lock; - #endif - uint8_t num; - }; -#endif - -// HW SPI PINS -#define SPI_BUS_CLK 14 -#define SPI_BUS_MOSI 13 -#define SPI_BUS_MISO 12 -#define SPI_BUS_SS 4 - -// Specify how the Panel handles row muxing: -// BINARY: Pins A-E map to rows 1-32 via binary decoding (default) -// STRAIGHT: Pins A-D are directly mapped to rows 1-4 -// SHIFTREG: A, B, C on Panel are connected to a shift register Clock, /Enable, Data -// SHIFTREG_ABC_BIN_DE: A-C are connected to Shift-Register Clock, Data, /Enable, D-E to binary decoder (crazy shit) -// SHIFTREG_SPI_SE: Like SHIFTREG, but you connect A and C on Panel to its Clock and Data output (and ground B). This will not work with fast_update enabled! -enum mux_patterns {BINARY, STRAIGHT, SHIFTREG_ABC, SHIFTREG_SPI_SE, SHIFTREG_ABC_BIN_DE}; - -// Specifies what blocking pattern the panel is using -// |AB|,|DB| -// |CD|,|CA| -// |AB|,|DB| -// |CD|,|CA| -enum block_patterns {ABCD, DBCA}; - -// This is how the scanning is implemented. LINE just scans it left to right, -// ZIGZAG jumps 4 rows after every byte, ZAGGII alse revereses every second byte -enum scan_patterns {LINE, ZIGZAG,ZZAGG, ZAGGIZ, WZAGZIG, VZAG, ZAGZIG, WZAGZIG2, ZZIAGG}; - -// Specifies speciffic driver chip. Most panels implement a standard shifted -// register (SHIFT). Other chips/panels may need special treatment in oder to work -enum driver_chips {SHIFT, FM6124, FM6126A}; - -// Specify the color order -enum color_orders {RRGGBB, RRBBGG, GGRRBB, GGBBRR, BBRRGG, BBGGRR}; - - -#define color_step (256 / PxMATRIX_COLOR_DEPTH) -#define color_half_step (int(color_step / 2)) -#define color_third_step (int(color_step / 3)) -#define color_two_third_step (int(color_third_step*2)) - -class PxMATRIX : public Adafruit_GFX { - public: - inline PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B); - inline PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B,uint8_t C); - inline PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B,uint8_t C,uint8_t D); - inline PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B,uint8_t C,uint8_t D,uint8_t E); - - inline void begin(uint8_t row_pattern, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t SS); - inline void begin(uint8_t row_pattern); - inline void begin(); - - inline void clearDisplay(void); - inline void clearDisplay(bool selected_buffer); - - // Updates the display - inline void display(uint16_t show_time); - inline void display(); - - // Draw pixels - inline void drawPixelRGB565(int16_t x, int16_t y, uint16_t color); - - inline void drawPixel(int16_t x, int16_t y, uint16_t color); - - inline void drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g,uint8_t b); - - // Does nothing for now (always returns 0) - uint8_t getPixel(int8_t x, int8_t y); - - // Converts RGB888 to RGB565 - uint16_t color565(uint8_t r, uint8_t g, uint8_t b); - - // Helpful for debugging (place in display update loop) - inline void displayTestPattern(uint16_t showtime); - - // Helpful for debugging (place in display update loop) - inline void displayTestPixel(uint16_t show_time); - - // FLush the buffer of the display - inline void flushDisplay(); - - // Rotate display - inline void setRotate(bool rotate); - - // Flip display - inline void setFlip(bool flip); - - // Helps to reduce display update latency on larger displays - inline void setFastUpdate(bool fast_update); - - // When using double buffering, this displays the draw buffer - inline void showBuffer(); - -#ifdef PxMATRIX_DOUBLE_BUFFER - // This copies the display buffer to the drawing buffer (or reverse) - inline void copyBuffer(bool reverse); -#endif - - // Control the minimum color values that result in an active pixel - inline void setColorOffset(uint8_t r, uint8_t g,uint8_t b); - - // Set the multiplex implemention {BINARY, STRAIGHT, SHIFTREG} (default is BINARY) - inline void setMuxPattern(mux_patterns mux_pattern); - - // Set the color order - inline void setColorOrder(color_orders color_order); - - // Set the time in microseconds that we pause after selecting each mux channel - // (May help if some rows are missing / the mux chip is too slow) - inline void setMuxDelay(uint8_t mux_delay_A, uint8_t mux_delay_B, uint8_t mux_delay_C, uint8_t mux_delay_D, uint8_t mux_delay_E); - - // Set the multiplex pattern {LINE, ZIGZAG, ZAGGIZ, WZAGZIG, VZAG, WZAGZIG2} (default is LINE) - inline void setScanPattern(scan_patterns scan_pattern); - - // Set the block pattern {ABCD, DBCA} (default is ABCD) - inline void setBlockPattern(block_patterns block_pattern); - - // Set the number of panels that make up the display area width (default is 1) - inline void setPanelsWidth(uint8_t panels); - - // Set the brightness of the panels (default is 255) - inline void setBrightness(uint8_t brightness); - - // Set driver chip type - inline void setDriverChip(driver_chips driver_chip); - - private: - - // the display buffer for the LED matrix - uint8_t *PxMATRIX_buffer; -#ifdef PxMATRIX_DOUBLE_BUFFER - uint8_t *PxMATRIX_buffer2; -#endif - - // GPIO pins - uint8_t _LATCH_PIN; - uint8_t _OE_PIN; - uint8_t _A_PIN; - uint8_t _B_PIN; - uint8_t _C_PIN; - uint8_t _D_PIN; - uint8_t _E_PIN; - - // SPI pins - uint8_t _SPI_CLK = SPI_BUS_CLK; - uint8_t _SPI_MOSI = SPI_BUS_MOSI; - uint8_t _SPI_MISO = SPI_BUS_MISO; - uint8_t _SPI_SS = SPI_BUS_SS; - - uint16_t _width; - uint16_t _height; - uint8_t _panels_width; - uint8_t _rows_per_buffer; - uint8_t _row_sets_per_buffer; - uint8_t _panel_width_bytes; - - // Color offset - uint8_t _color_R_offset; - uint8_t _color_G_offset; - uint8_t _color_B_offset; - - // Panel Brightness - uint8_t _brightness; - - // Color pattern that is pushed to the display - uint8_t _display_color; - - // Holds some pre-computed values for faster pixel drawing - uint32_t *_row_offset; - - // Holds the display row pattern type - uint8_t _row_pattern; - - // Number of bytes in one color - uint8_t _pattern_color_bytes; - - // Total number of bytes that is pushed to the display at a time - // 3 * _pattern_color_bytes - uint16_t _buffer_size; - uint16_t _send_buffer_size; - - // This is for double buffering - bool _active_buffer; - bool updateBuffer = false; - - // Display and color engine - bool _rotate; - bool _flip; - bool _fast_update; - - // Holds multiplex pattern - mux_patterns _mux_pattern; - - //Holdes the color order - color_orders _color_order; - - uint8_t _mux_delay_A; - uint8_t _mux_delay_B; - uint8_t _mux_delay_C; - uint8_t _mux_delay_D; - uint8_t _mux_delay_E; - - // Holds the scan pattern - scan_patterns _scan_pattern; - - // Holds the block pattern - block_patterns _block_pattern; - - // Holds the used driver chip - driver_chips _driver_chip; - - // Used for test pattern - uint16_t _test_pixel_counter; - uint16_t _test_line_counter; - unsigned long _test_last_call; - - // Generic function that draw one pixel -inline void fillMatrixBuffer(int16_t x, int16_t y, uint8_t r, uint8_t g,uint8_t b, bool selected_buffer); - - // Init code common to both constructors -inline void init(uint16_t width, uint16_t height ,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B); - - // Light up LEDs and hold for show_time microseconds -inline void latch(uint16_t show_time ); - - // Set row multiplexer -inline void set_mux(uint8_t value, bool random_access); - -inline void spi_init(); - -// Write configuration register in some driver chips -inline void writeRegister(uint16_t reg_value, uint8_t reg_position); -inline void fm612xWriteRegister(uint16_t reg_value, uint8_t reg_position); -}; - -// Pass 8-bit (each) R,G,B, get back 16-bit packed color -inline uint16_t PxMATRIX::color565(uint8_t r, uint8_t g, uint8_t b) { - return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); -} - -// Init code common to both constructors -inline void PxMATRIX::init(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A, uint8_t B){ - _LATCH_PIN = LATCH; - _OE_PIN = OE; - _display_color=0; - - _A_PIN = A; - _B_PIN = B; - - _width = width; - _height = height; - - _buffer_size = (_width*_height * 3 / 8); - - _brightness=255; - _panels_width = 1; - - _rows_per_buffer = _height/2; - _panel_width_bytes = (_width/_panels_width)/8; - - _active_buffer=false; - - _color_R_offset=0; - _color_G_offset=0; - _color_B_offset=0; - - _test_last_call=0; - _test_pixel_counter=0; - _test_line_counter=0; - _rotate=0; - _flip=0; - _fast_update=0; - - _row_pattern=0; - _scan_pattern=LINE; - _block_pattern=ABCD; - _driver_chip=SHIFT; - - _mux_delay_A=0; - _mux_delay_B=0; - _mux_delay_C=0; - _mux_delay_D=0; - _mux_delay_E=0; - - PxMATRIX_buffer= new uint8_t[PxMATRIX_COLOR_DEPTH*_buffer_size]; - #ifdef PxMATRIX_DOUBLE_BUFFER - PxMATRIX_buffer2=new uint8_t[PxMATRIX_COLOR_DEPTH*_buffer_size]; - #endif - -} - -#ifdef ESP32 -inline void PxMATRIX::fm612xWriteRegister(uint16_t reg_value, uint8_t reg_position) -{ - spi_t * spi = SPI.bus(); - // reg_value = 0x1234; debug - - for(int i=0; i<47; i++) - SPI_2BYTE(reg_value); - - spiSimpleTransaction(spi); - - spi->dev->mosi_dlen.usr_mosi_dbitlen = 16-reg_position-1; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - spi->dev->data_buf[0] = reg_value>>8; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - - GPIO_REG_SET(1 << _LATCH_PIN); - - spi->dev->mosi_dlen.usr_mosi_dbitlen = (reg_position-8)-1; - spi->dev->data_buf[0] = reg_value>>(reg_position-8); - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - spiEndTransaction(spi); - - SPI_BYTE(reg_value&0xff); - - GPIO_REG_CLEAR(1 << _LATCH_PIN); - -} -#else -inline void PxMATRIX::writeRegister(uint16_t reg_value, uint8_t reg_position) -{ - if (_driver_chip == FM6124 || _driver_chip == FM6126A){ - - /*if (_driver_chip == FM6124) { - Serial.println("\nFM6124 - REG: " + String(reg_position)); - } else { - Serial.println("\nFM6126A - REG: " + String(reg_position)); - }*/ - - // All FM6126A code is based on the excellent guesswork by shades66 in https://github.com/hzeller/rpi-rgb-led-matrix/issues/746 - // Register 12 - brightness/gain settings, three 6bit values, aaaaaabbbbbbcccccc a= darkness? - // seems to add red to the background when the leds are off, b=main brightness c=finer brightness - // (i'm not sure if b & c are actually as 12 bit value but with b set to all 1's the value in c doesn't seem to make much difference) - - // Register 13 - not sure what it's doing yet, just that 1 specific bit within seems to be an overall enable function. - - // Now set all the values at the top to the same value for each of register 12/13 to get the same settings across the panel, the current code loads different settings into each 32 columns. - // clocking in the register is simply clocking in the value (i've 2 panels so 128bits of data) and for the last 12/13 bits depending on the register setting the latch to high. the final drop of latch to low clocks in the configuration. this is done by sending the same value to r1/r2/g1/g2/b1/b2 at the same time to load the config into all the FM6126 chips - - // Some necessary magic bit fields - // b12 - 1 adds red tinge - // b12 - 9/8/7/6/5 = 4 bit brightness - // b13 - 9 =1 screen on - // b13 - 6 =1 screen off - pinMode(_SPI_CLK,OUTPUT); - pinMode(_SPI_MOSI,OUTPUT); - digitalWrite(_SPI_CLK,HIGH); // CCK LOW - digitalWrite(_OE_PIN,LOW); - digitalWrite(_LATCH_PIN,HIGH); - digitalWrite(_A_PIN,HIGH); - digitalWrite(_B_PIN,LOW); - digitalWrite(_C_PIN,LOW); - digitalWrite(_D_PIN,LOW); - - uint8_t reg_bit=0; - for (uint32_t bit_counter=0; bit_counter < _send_buffer_size*8; bit_counter++) - { - reg_bit=bit_counter%16; - if ((reg_value>>reg_bit)&1) - digitalWrite(_SPI_MOSI,HIGH); - else - digitalWrite(_SPI_MOSI,LOW); - - delay(1); - digitalWrite(_SPI_CLK,LOW); // CLK HIGH - delay(1); - digitalWrite(_SPI_CLK,HIGH); // CLK LOW - delay(1); - if ((bit_counter == (_send_buffer_size*8 - reg_position-1))) - { - digitalWrite(_LATCH_PIN,LOW); - } - } - digitalWrite(_LATCH_PIN,HIGH); - } - digitalWrite(_OE_PIN,HIGH); - -} -#endif - -inline void PxMATRIX::setDriverChip(driver_chips driver_chip) -{ - _driver_chip=driver_chip; - - if (driver_chip == FM6124 || driver_chip == FM6126A){ - - uint16_t b12a=0b0111111111111111; //亮度: high - b12a=0b0111100011111111; //亮度: low - // uint16_t b12b=0b0111100000111111; - // uint16_t b12c=0b0111111111111111; - // uint16_t b12d=0b0111100000111111; - - uint16_t b13a=0b0000000001000000; - // uint16_t b13b=0b0000000001000000; - // uint16_t b13c=0b0000000001000000; - // uint16_t b13d=0b0000000001000000; - -#ifdef ESP32 - pinMode(_OE_PIN, OUTPUT); - pinMode(_LATCH_PIN, OUTPUT); - digitalWrite(_OE_PIN, HIGH); - pinMode(_LATCH_PIN, LOW); - - fm612xWriteRegister(b12a,11); - fm612xWriteRegister(b13a,12); - -#else - writeRegister(b12a, 12); - writeRegister(b13a, 13); -#endif - - - } -} - -inline void PxMATRIX::setMuxPattern(mux_patterns mux_pattern) -{ - _mux_pattern=mux_pattern; - - // We handle the multiplexing in the library and activate one of for - // row drivers --> need A,B,C,D pins - if (_mux_pattern==STRAIGHT) - { - pinMode(_C_PIN, OUTPUT); - pinMode(_D_PIN, OUTPUT); - } - - if (_mux_pattern==SHIFTREG_SPI_SE) - { - pinMode(_B_PIN, OUTPUT); // B is used as /Enable for row mux - digitalWrite(_B_PIN,LOW); // Enable output of row mux - } - - if (_mux_pattern==SHIFTREG_ABC) - { - pinMode(_A_PIN, OUTPUT); // A is used as MUX_CLK - pinMode(_B_PIN, OUTPUT); // B is used as MUX_ENABLE - pinMode(_C_PIN, OUTPUT); // C is used as MUX_DATA - digitalWrite(_B_PIN,LOW); // Enable output of row mux - } - - if (_mux_pattern==SHIFTREG_ABC_BIN_DE) - { - pinMode(_A_PIN, OUTPUT); // A is used as MUX_CLK - pinMode(_B_PIN, OUTPUT); // B is used as MUX_DATA - pinMode(_C_PIN, OUTPUT); // C is used as MUX_ENABLE - pinMode(_D_PIN, OUTPUT); // D is 4th bit of row - pinMode(_E_PIN, OUTPUT); // E is 5th bit of row - digitalWrite(_C_PIN,LOW); // Enable output of row mux - } -} - - -inline void PxMATRIX::setColorOrder(color_orders color_order) -{ - _color_order=color_order; -} - - - -inline void PxMATRIX::setMuxDelay(uint8_t mux_delay_A, uint8_t mux_delay_B, uint8_t mux_delay_C, uint8_t mux_delay_D, uint8_t mux_delay_E) -{ - _mux_delay_A=mux_delay_A; - _mux_delay_B=mux_delay_B; - _mux_delay_C=mux_delay_C; - _mux_delay_D=mux_delay_D; - _mux_delay_E=mux_delay_E; -} - -inline void PxMATRIX::setScanPattern(scan_patterns scan_pattern) -{ - _scan_pattern=scan_pattern; -} - -inline void PxMATRIX::setBlockPattern(block_patterns block_pattern) -{ - _block_pattern=block_pattern; -} - -inline void PxMATRIX::setPanelsWidth(uint8_t panels) { - _panels_width=panels; - _panel_width_bytes = (_width/_panels_width)/8; -} - -inline void PxMATRIX::setRotate(bool rotate) { - _rotate=rotate; -} - -inline void PxMATRIX::setFlip(bool flip) { - _flip=flip; -} - -inline void PxMATRIX::setFastUpdate(bool fast_update) { - _fast_update=fast_update; -} - -inline void PxMATRIX::setBrightness(uint8_t brightness) { - _brightness=brightness; -} - - -inline PxMATRIX::PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B) : Adafruit_GFX(width+ADAFRUIT_GFX_EXTRA, height) -{ - init(width, height, LATCH, OE, A, B); -} - -inline PxMATRIX::PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B,uint8_t C) : Adafruit_GFX(width+ADAFRUIT_GFX_EXTRA, height) -{ - _C_PIN = C; - init(width, height, LATCH, OE, A, B); -} - -inline PxMATRIX::PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B,uint8_t C,uint8_t D) : Adafruit_GFX(width+ADAFRUIT_GFX_EXTRA, height) -{ - _C_PIN = C; - _D_PIN = D; - init(width, height, LATCH, OE, A, B); -} - -inline PxMATRIX::PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B,uint8_t C,uint8_t D, uint8_t E) : Adafruit_GFX(width+ADAFRUIT_GFX_EXTRA, height) -{ - _C_PIN = C; - _D_PIN = D; - _E_PIN = E; - init(width, height, LATCH, OE, A, B); -} - -inline void PxMATRIX::drawPixel(int16_t x, int16_t y, uint16_t color) { - drawPixelRGB565(x, y, color); -} - -inline void PxMATRIX::showBuffer() { - _active_buffer=!_active_buffer; -} - -#ifdef PxMATRIX_DOUBLE_BUFFER -inline void PxMATRIX::copyBuffer(bool reverse = false) { - // This copies the display buffer to the drawing buffer (or reverse) - // You may need this in case you rely on the framebuffer to always contain the last frame - // _active_buffer = true means that PxMATRIX_buffer2 is displayed - if(_active_buffer ^ reverse) { - memcpy(PxMATRIX_buffer, PxMATRIX_buffer2, PxMATRIX_COLOR_DEPTH*_buffer_size); - } else { - memcpy(PxMATRIX_buffer2, PxMATRIX_buffer, PxMATRIX_COLOR_DEPTH*_buffer_size); - } -} -#endif - -inline void PxMATRIX::setColorOffset(uint8_t r, uint8_t g,uint8_t b) -{ - _color_R_offset=r; - _color_G_offset=g; - _color_B_offset=b; -} - -inline void PxMATRIX::fillMatrixBuffer(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b,bool selected_buffer) -{ - - - if (r>_color_R_offset) - r-=_color_R_offset; - else - r=0; - if (g>_color_G_offset) - g-=_color_G_offset; - else - g=0; - if (b>_color_B_offset) - b-=_color_B_offset; - else - b=0; - - if (_block_pattern==DBCA) - { - - - // Every matrix is segmented in 8 blocks - 2 in X, 4 in Y direction - // |AB| - // |CD| - // |AB| - // |CD| - // Have to rewrite this block suff and move to the scan pattern section - this will only work for chaining up to 2 panels - - if (_panels_width>1) // Only works for two panels - { - if ((x>=_width/4) && (x<_width/2)) - x+=_width/4; - else if ((x>=_width/2) && (x<_width*3/4)) - x-=_width/4; - } - - uint16_t y_block = y*4/_height; - uint16_t x_block = x*2*_panels_width/_width; - - // Swapping A & D - if (!(y_block%2)) // Even y block - { - if (!(x_block%2)) // Left side of panel - { - x+=_width/2/_panels_width; - y+=_height/4; - } - } - else // Odd y block - { - if (x_block%2) // Right side of panel - { - x-=_width/2/_panels_width; - y-=_height/4; - - } - } - - } - - if (_rotate){ - uint16_t temp_x=x; - x=y; - y=_height-1-temp_x; - } - - // Panels are naturally flipped - if (!_flip) - x =_width - 1 -x; - - if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) - return; - - if (_color_order!= RRGGBB) - { - uint8_t r_temp=r; - uint8_t g_temp=g; - uint8_t b_temp=b; - - - switch (_color_order) - { - case (RRGGBB): break; - case (RRBBGG): g=b_temp; b=g_temp; break; - case (GGRRBB): r=g_temp; g=r_temp; break; - case (GGBBRR): r=g_temp; g=b_temp; b=r_temp; break; - case (BBRRGG): r=b_temp; g=r_temp; b=g_temp; break; - case (BBGGRR): r=b_temp; g=g_temp; b=r_temp; break; - } - } - - uint32_t base_offset; - uint32_t total_offset_r=0; - uint32_t total_offset_g=0; - uint32_t total_offset_b=0; - - if (_scan_pattern==WZAGZIG || _scan_pattern==VZAG || _scan_pattern==WZAGZIG2) - { - // get block coordinates and constraints - uint8_t rows_per_buffer = _height/2; - uint8_t rows_per_block = rows_per_buffer/2; - // this is a defining characteristic of WZAGZIG and VZAG: - // two byte alternating chunks bottom up for WZAGZIG - // two byte up down down up for VZAG - uint8_t cols_per_block = 16; - uint8_t panel_width = _width/_panels_width; - uint8_t blocks_x_per_panel = panel_width/cols_per_block; - uint8_t panel_index = x/panel_width; - // strip down to single panel coordinates, restored later using panel_index - x = x%panel_width; - uint8_t base_y_offset = y/rows_per_buffer; - uint8_t buffer_y = y%rows_per_buffer; - uint8_t block_x = x/cols_per_block; - uint8_t block_x_mod = x%cols_per_block; - uint8_t block_y = buffer_y/rows_per_block; // can only be 0/1 for height/pattern=4 - uint8_t block_y_mod = buffer_y%rows_per_block; - - // translate block address to new block address - // invert block_y so remaining translation will be more sane - uint8_t block_y_inv = 1 - block_y; - uint8_t block_x_inv = blocks_x_per_panel - block_x - 1; - uint8_t block_linear_index; - if (_scan_pattern==WZAGZIG2) { - block_linear_index = block_x_inv * 2 + block_y; - } - else if (_scan_pattern==WZAGZIG) - { - // apply x/y block transform for WZAGZIG, only works for height/pattern=4 - block_linear_index = block_x_inv * 2 + block_y_inv; - } - else if (_scan_pattern==VZAG) - { - // apply x/y block transform for VZAG, only works for height/pattern=4 and 32x32 panels until a larger example is found - block_linear_index = block_x_inv * 3 * block_y + block_y_inv * (block_x_inv + 1); - } - // render block linear index back into normal coordinates - uint8_t new_block_x = block_linear_index % blocks_x_per_panel; - uint8_t new_block_y = 1 - block_linear_index/blocks_x_per_panel; - x = new_block_x * cols_per_block + block_x_mod + panel_index * panel_width; - y = new_block_y * rows_per_block + block_y_mod + base_y_offset * rows_per_buffer; - } - - // This code sections computes the byte in the buffer that will be manipulated. - if (_scan_pattern!=LINE && _scan_pattern!=WZAGZIG && _scan_pattern!=VZAG && _scan_pattern!=WZAGZIG2) - { - // Precomputed row offset values - base_offset=_row_offset[y]-(x/8)*2; - uint8_t row_sector=0; - uint16_t row_sector__offset=_width/4; - for (uint8_t yy = 0; yy<_height; yy+=2*_row_pattern) - { - if ((yy<=y) && (y 1 - // i.e.: 32x32 panel with 1/8 scan (A/B/C lines) -> 32/2/8 = 2 - uint8_t vert_index_in_buffer = (y%_rows_per_buffer)/_row_pattern; // which set of rows per buffer - - // can only ever be 0/1 since there are only ever 2 separate input sets present for this variety of panels (R1G1B1/R2G2B2) - uint8_t which_buffer = y/_rows_per_buffer; - uint8_t x_byte = x/8; - // assumes panels are only ever chained for more width - uint8_t which_panel = x_byte/_panel_width_bytes; - uint8_t in_row_byte_offset = x_byte%_panel_width_bytes; - // this could be pretty easily extended to vertical stacking as well - total_offset_r = _row_offset[y] - in_row_byte_offset - _panel_width_bytes*(_row_sets_per_buffer*(_panels_width*which_buffer + which_panel) + vert_index_in_buffer); - } - - - uint8_t bit_select = x%8; - - - // Normally the bytes in one buffer would be sequencial, e.g. - // 0-1-2-3- - // 0-1-2-3- - // hence the upper and lower row start with [OL|OH]. - // - // However some panels have a byte wise row-changing scanning pattern and/or a bit changing pattern that we have to take case of - // For example [1L|1H] [3L|3H] for ZIGZAG or [0L|0H] [2L|2H] for ZAGZIG - // | \ | \ | / | / - // [0L|0H] [2L|2H] [1L|1H] [3L|3H] - // - // For example [0H|1L] [2H|3L] for ZZAGG or [0L|1L] [2L|3L] for ZZIAGG - // | \ | \ | / | / - // [0L|1H] [2L|3H] [0H|1H] [2H|3H] - // - // - // In order to make the pattern start on both rows with [0L|0H] we have to add / subtract values to / from total_offset_r and bit_select - if ((y%(_row_pattern*2))<_row_pattern) - { - // Variant of ZAGZIG pattern with bit oder reversed on lower part (starts on upper part) - if (_scan_pattern==ZAGGIZ) - { - total_offset_r--; - bit_select = 7-bit_select; - } - - // Row changing pattern (starts on upper part) - if (_scan_pattern==ZAGZIG) - total_offset_r--; - - // Byte split pattern - like ZAGZIG but after every 4 bit (starts on upper part) - if (_scan_pattern == ZZIAGG ) - { - if (bit_select>3) - - bit_select +=4; - else - total_offset_r--; - } - - // Byte split pattern (lower part) - if (_scan_pattern==ZZAGG) - if (bit_select>3) total_offset_r--; - } - else - { - - if (_scan_pattern==ZIGZAG) - total_offset_r--; - - // Byte split pattern - like ZAGZIG but after every 4 bit (starts on upper part) - if (_scan_pattern == ZZIAGG ) - { - - if (bit_select>3) - { - total_offset_r--; - bit_select -=4; - } - } - - // Byte split pattern (upper part) - if (_scan_pattern==ZZAGG) - { - if (bit_select<=3) - bit_select += 4; - else - { - bit_select -=4; - total_offset_r--; - } - } - } - - total_offset_g=total_offset_r-_pattern_color_bytes; - total_offset_b=total_offset_g-_pattern_color_bytes; - -uint8_t *PxMATRIX_bufferp = PxMATRIX_buffer; - -#ifdef PxMATRIX_DOUBLE_BUFFER - - PxMATRIX_bufferp = selected_buffer ? PxMATRIX_buffer2 : PxMATRIX_buffer; - -#endif - - r = r >> (8-PxMATRIX_COLOR_DEPTH); - g = g >> (8-PxMATRIX_COLOR_DEPTH); - b = b >> (8-PxMATRIX_COLOR_DEPTH); - - //Color interlacing - for (int this_color_bit=0; this_color_bit> this_color_bit) & 0x01) - PxMATRIX_bufferp[this_color_bit*_buffer_size+total_offset_r] |=_BV(bit_select); - else - PxMATRIX_bufferp[this_color_bit*_buffer_size+total_offset_r] &= ~_BV(bit_select); - - if ((g >> this_color_bit) & 0x01) - PxMATRIX_bufferp[this_color_bit*_buffer_size+total_offset_g] |=_BV(bit_select); - else - PxMATRIX_bufferp[this_color_bit*_buffer_size+total_offset_g] &= ~_BV(bit_select); - - if ((b >> this_color_bit) & 0x01) - PxMATRIX_bufferp[this_color_bit*_buffer_size+total_offset_b] |=_BV(bit_select); - else - PxMATRIX_bufferp[this_color_bit*_buffer_size+total_offset_b] &= ~_BV(bit_select); - } -} - -inline void PxMATRIX::drawPixelRGB565(int16_t x, int16_t y, uint16_t color) { - uint8_t r = ((((color >> 11) & 0x1F) * 527) + 23) >> 6; - uint8_t g = ((((color >> 5) & 0x3F) * 259) + 33) >> 6; - uint8_t b = (((color & 0x1F) * 527) + 23) >> 6; -#ifdef PxMATRIX_DOUBLE_BUFFER - fillMatrixBuffer(x, y, r, g, b, !_active_buffer); -#else - fillMatrixBuffer(x, y, r, g, b, false); -#endif -} - -inline void PxMATRIX::drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g,uint8_t b) { -#ifdef PxMATRIX_DOUBLE_BUFFER - fillMatrixBuffer(x, y, r, g, b, !_active_buffer); -#else - fillMatrixBuffer(x, y, r, g, b, false); -#endif -} - -// the most basic function, get a single pixel -inline uint8_t PxMATRIX::getPixel(int8_t x, int8_t y) { - return (0);//PxMATRIX_buffer[x+ (y/8)*LCDWIDTH] >> (y%8)) & 0x1; -} - -inline void PxMATRIX::begin() -{ - begin(8); - -} - -void PxMATRIX::begin(uint8_t row_pattern, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t SS) -{ - - _SPI_CLK = CLK; - _SPI_MOSI = MOSI; - _SPI_MISO = MISO; - _SPI_SS = SS; - begin(row_pattern); - -} - -void PxMATRIX::spi_init(){ - - #ifdef ESP32 - SPI.begin(_SPI_CLK, _SPI_MISO, _SPI_MOSI, _SPI_SS); - #else - SPI.begin(); - #endif - - #if defined(ESP32) || defined(ESP8266) - SPI.setFrequency(PxMATRIX_SPI_FREQUENCY); - #endif - - SPI.setDataMode(SPI_MODE0); - SPI.setBitOrder(MSBFIRST); - -} - -void PxMATRIX::begin(uint8_t row_pattern) { - - - - _row_pattern=row_pattern; - if (_row_pattern==4) - _scan_pattern=ZIGZAG; - _mux_pattern = BINARY; - _color_order=RRGGBB; - - - _pattern_color_bytes=(_height/_row_pattern)*(_width/8); - _row_sets_per_buffer = _rows_per_buffer/_row_pattern; - _send_buffer_size=_pattern_color_bytes*3; - - - - spi_init(); - - - pinMode(_OE_PIN, OUTPUT); - pinMode(_LATCH_PIN, OUTPUT); - pinMode(_A_PIN, OUTPUT); - pinMode(_B_PIN, OUTPUT); - digitalWrite(_A_PIN, LOW); - digitalWrite(_B_PIN, LOW); - digitalWrite(_OE_PIN, HIGH); - - if (_row_pattern >=8) - { - pinMode(_C_PIN, OUTPUT); - digitalWrite(_C_PIN, LOW); - } - if (_row_pattern >=16) - { - pinMode(_D_PIN, OUTPUT); - digitalWrite(_D_PIN, LOW); - } - if (_row_pattern >=32) - { - pinMode(_E_PIN, OUTPUT); - digitalWrite(_E_PIN, LOW); - } - - // Precompute row offset values - _row_offset=new uint32_t[_height]; - for (uint8_t yy=0; yy<_height;yy++) - _row_offset[yy]=((yy)%_row_pattern)*_send_buffer_size+_send_buffer_size-1; - -} - -void PxMATRIX::set_mux(uint8_t value, bool random_access = false) -{ - - if (_mux_pattern==BINARY) - { - if (value & 0x01) - digitalWrite(_A_PIN,HIGH); - else - digitalWrite(_A_PIN,LOW); - if (_mux_delay_A) delayMicroseconds(_mux_delay_A); - - if (value & 0x02) - digitalWrite(_B_PIN,HIGH); - else - digitalWrite(_B_PIN,LOW); - if (_mux_delay_B) delayMicroseconds(_mux_delay_B); - - if (_row_pattern>=8) - { - - if (value & 0x04) - digitalWrite(_C_PIN,HIGH); - else - digitalWrite(_C_PIN,LOW); - if (_mux_delay_C) delayMicroseconds(_mux_delay_C); - } - - - if (_row_pattern>=16) - { - if (value & 0x08) - digitalWrite(_D_PIN,HIGH); - else - digitalWrite(_D_PIN,LOW); - if (_mux_delay_D) delayMicroseconds(_mux_delay_D); - } - - if (_row_pattern>=32) - { - if (value & 0x10) - digitalWrite(_E_PIN,HIGH); - else - digitalWrite(_E_PIN,LOW); - if (_mux_delay_E) delayMicroseconds(_mux_delay_E); - } - } - - if (_mux_pattern==STRAIGHT) - { - if (value==0) - digitalWrite(_A_PIN,LOW); - else - digitalWrite(_A_PIN,HIGH); - - if (value==1) - digitalWrite(_B_PIN,LOW); - else - digitalWrite(_B_PIN,HIGH); - - if (value==2) - digitalWrite(_C_PIN,LOW); - else - digitalWrite(_C_PIN,HIGH); - - if (value==3) - digitalWrite(_D_PIN,LOW); - else - digitalWrite(_D_PIN,HIGH); - } - - if (_mux_pattern==SHIFTREG_SPI_SE) { - // A, B, C on Panel are connected to a shift register Clock, /enable, Data - uint8_t rowmask[4] = {0,0,0,0}; - if(_row_pattern > 16) { - rowmask[(31-value)/8] = (1<<(value%8)); - SPI_TRANSFER(rowmask,4); - } else { - rowmask[(15-value)/8] = (1<<(value%8)); - SPI_TRANSFER(rowmask,2); - } - } - - if (_mux_pattern==SHIFTREG_ABC) { - // A,B,C are connected to a shift register Clock, /Enable, Data - if(random_access) { - // Clock out all row mux bits to make sure random access is possible - uint8_t r = _row_pattern; - while(r-- > 0) { - digitalWrite(_C_PIN, (value==r) ); // Shift out 1 for selected row - digitalWrite(_A_PIN, HIGH); // Clock out this bit - digitalWrite(_A_PIN, LOW); - } - } else { - // Just shift the row mux by one for incremental access - digitalWrite(_C_PIN, (value==0) ); // Shift out 1 for line 0, 0 otherwise - digitalWrite(_A_PIN, HIGH); // Clock out this bit - digitalWrite(_A_PIN, LOW); - } - } - - if (_mux_pattern==SHIFTREG_ABC_BIN_DE) { - // A-C are connected to Shift-Register Clock, Data, /Enable, D-E to binary decoder (crazy shit) - // Shift-Register is 8 rows wide, D-E select different Blocks of 8 rows - digitalWrite(_D_PIN, (value>>3)&1 ); - digitalWrite(_E_PIN, (value>>4)&1 ); - value = value % 8; - if(random_access) { - // Clock out all row mux bits to make sure random access is possible - uint8_t r = 8; - while(r-- > 0) { - digitalWrite(_B_PIN, (value==r) ); // Shift out 1 for selected row - digitalWrite(_A_PIN, HIGH); // Clock out this bit - digitalWrite(_A_PIN, LOW); - } - } else { - // Just shift the row mux by one for incremental access - digitalWrite(_B_PIN, (value==0) ); // Shift out 1 for line 0, 0 otherwise - digitalWrite(_A_PIN, HIGH); // Clock out this bit - digitalWrite(_A_PIN, LOW); - } - } - -} - -void PxMATRIX::latch(uint16_t show_time ) -{ - - if (_driver_chip==SHIFT) - { - //digitalWrite(_OE_PIN,0); // <<< remove this - digitalWrite(_LATCH_PIN,HIGH); - //delayMicroseconds(10); - digitalWrite(_LATCH_PIN,LOW); - - //delayMicroseconds(10); - if (show_time >0) - { - //delayMicroseconds(show_time); - digitalWrite(_OE_PIN,0); - unsigned long start_time=micros(); - while ((micros()-start_time)dev->mosi_dlen.usr_mosi_dbitlen = 4; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - spi->dev->data_buf[0] = v; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - - GPIO_REG_SET( 1 << _LATCH_PIN); - - spi->dev->mosi_dlen.usr_mosi_dbitlen = 2; - spi->dev->data_buf[0] = v<<5; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - GPIO_REG_CLEAR( 1 << _LATCH_PIN); - - spiEndTransaction(spi); - set_mux(i); - #else - #if defined(ESP8266) || defined(ESP32) - pinMode(_SPI_CLK, SPECIAL); - pinMode(_SPI_MOSI, SPECIAL); - #endif - SPI_TRANSFER(&PxMATRIX_bufferp[_display_color*_buffer_size+i*_send_buffer_size],_send_buffer_size-1); - pinMode(_SPI_CLK, OUTPUT); - pinMode(_SPI_MOSI, OUTPUT); - pinMode(_SPI_MISO, OUTPUT); - pinMode(_SPI_SS, OUTPUT); - set_mux(i); - - uint8_t v = PxMATRIX_bufferp[_display_color*_buffer_size+i*_send_buffer_size + _send_buffer_size - 1]; - for (uint8_t this_byte = 0; this_byte < 8; this_byte++) { - if (((v >> (7 - this_byte)) & 1)) - GPIO_REG_SET( 1 << _SPI_MOSI); - else - GPIO_REG_CLEAR( 1 << _SPI_MOSI); - GPIO_REG_SET( 1 << _SPI_CLK); - GPIO_REG_CLEAR( 1 << _SPI_CLK); - - if (this_byte == 4) - //GPIO_REG_SET( 1 << _LATCH_PIN); - digitalWrite(_LATCH_PIN, HIGH); - } - //GPIO_REG_WRITE(GPIO_ spi_init(); - - digitalWrite(_LATCH_PIN, LOW); - //GPIO_REG_SET( 1 << _OE_PIN); - digitalWrite(_OE_PIN, 0); //<<<< insert this - unsigned long start_time = micros(); - - while ((micros()-start_time)=PxMATRIX_COLOR_DEPTH) - { - _display_color=0; - } -} - -void PxMATRIX::flushDisplay(void) { - for (int ii=0;ii<_send_buffer_size;ii++) - SPI_BYTE(0x00); -} - -void PxMATRIX::displayTestPattern(uint16_t show_time) { - - if ((millis()-_test_last_call)>500) - { - flushDisplay(); - for (int ii=0;ii<=_test_pixel_counter;ii++) - SPI_BYTE(0xFF); - _test_last_call=millis(); - _test_pixel_counter++; - } - - if (_test_pixel_counter>_send_buffer_size) - - { - _test_pixel_counter=0; - _test_line_counter++; - flushDisplay(); - } - - if (_test_line_counter> (_height/2)) - _test_line_counter=0; - - digitalWrite(_A_PIN,HIGH); - delayMicroseconds(1); - digitalWrite(_B_PIN,HIGH); - delayMicroseconds(1); - digitalWrite(_C_PIN,HIGH); - delayMicroseconds(1); - digitalWrite(_D_PIN,HIGH); - delayMicroseconds(1); - digitalWrite(_E_PIN,HIGH); - delayMicroseconds(1); - - digitalWrite(_A_PIN,LOW); - delayMicroseconds(1); - digitalWrite(_B_PIN,LOW); - delayMicroseconds(1); - digitalWrite(_C_PIN,LOW); - delayMicroseconds(1); - digitalWrite(_D_PIN,LOW); - delayMicroseconds(1); - digitalWrite(_E_PIN,LOW); - delayMicroseconds(1); - set_mux(_test_line_counter, true); - - latch(show_time); -} - -void PxMATRIX::displayTestPixel(uint16_t show_time) { - if ((millis()-_test_last_call)>500) - { - flushDisplay(); - uint16_t blanks = _test_pixel_counter/8; - SPI_BYTE(1<<_test_pixel_counter%8); - while (blanks){ - SPI_BYTE(0x00); - blanks--; - } - _test_last_call=millis(); - _test_pixel_counter++; - } - - if (_test_pixel_counter>_send_buffer_size/3*8) - - { - _test_pixel_counter=0; - _test_line_counter++; - } - - if (_test_line_counter> (_height/2)) - _test_line_counter=0; - - digitalWrite(_A_PIN,HIGH); - delayMicroseconds(1); - digitalWrite(_B_PIN,HIGH); - delayMicroseconds(1); - digitalWrite(_C_PIN,HIGH); - delayMicroseconds(1); - digitalWrite(_D_PIN,HIGH); - delayMicroseconds(1); - digitalWrite(_E_PIN,HIGH); - delayMicroseconds(1); - - digitalWrite(_A_PIN,LOW); - delayMicroseconds(1); - digitalWrite(_B_PIN,LOW); - delayMicroseconds(1); - digitalWrite(_C_PIN,LOW); - delayMicroseconds(1); - digitalWrite(_D_PIN,LOW); - delayMicroseconds(1); - digitalWrite(_E_PIN,LOW); - delayMicroseconds(1); - - set_mux(_test_line_counter, true); - - latch(show_time); -} - -void PxMATRIX::clearDisplay(void) { -#ifdef PxMATRIX_DOUBLE_BUFFER - clearDisplay(!_active_buffer); -#else - clearDisplay(false); -#endif -} -// void * memset ( void * ptr, int value, size_t num ); - -// clear everything -void PxMATRIX::clearDisplay(bool selected_buffer) { -#ifdef PxMATRIX_DOUBLE_BUFFER - if(selected_buffer) - memset(PxMATRIX_buffer2, 0, PxMATRIX_COLOR_DEPTH*_buffer_size); - else - memset(PxMATRIX_buffer, 0, PxMATRIX_COLOR_DEPTH*_buffer_size); -#else - memset(PxMATRIX_buffer, 0, PxMATRIX_COLOR_DEPTH*_buffer_size); -#endif -} - -#endif diff --git a/index_html.h b/index_html.h index be1023b..27e0944 100644 --- a/index_html.h +++ b/index_html.h @@ -175,6 +175,7 @@ const char html_page_index[] PROGMEM = R"rawliteral(

N-Tools Uhr VPx

`VERSION`

`ID`

+ lokale IP: `LOCALIP`