Your new topic does not fit any of the above??? Check first. Then post here. Thanks.

Moderator: igrr

User avatar
By Barnabybear
#65065 Hi, Chris. I spent ages on this glad to help if I can. The port mapping is here:
https://esp8266.ru/esp8266-gpio-register/
And the second table below lists the registers for setting in/out pullups etc.
https://esp8266.ru/esp8266-pin-register-strapping/

Basicaly for outputs there are two 16 bit registers:
Code: Select allGPIO_OUT_W1TS // Write 1 To Set.
GPIO_OUT_W1TC // Write 1 To Clear.

So if the GPIO is set as an output and you write a 1 to a bit position the corresponding GPIO will be set or cleared depending on which register you wrote to. If I remember correctly the bit positions correspond with the GPIO numbers apart for GPIO16 which is in the clock register.
Code: Select allWRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS, 0xF000);  // set gpio 12 -> 15 output high / off


I've attached a sketch below with some working examples. It’s a 4 channel zero cross dimmer and won’t run without a 100Hz / 120Hz clock on pin 4 but will give you some ideas. GPIO 15 / D8 is just so I could debug with the logic analyser. I find it hard to track posts on here so PM me if you need any help.

Code: Select all#include <ESP8266WiFi.h>
#include <E131.h>

// set the pin numbers of the in/outputs
int output_1 = 12; // (D6) pin number of output 1 to triac
int output_2 = 13; // (D7) pin number of output 2 to triac
int output_3 = 14; // (D5) pin number of output 3 to triac
int output_4 = 16; // (D0) pin number of output 4 to triac
int output_D = 15; // (D8) debug waveform output
int input_zc = 4; // (D2) pin number of zero cross input

// variables for the DMX value & dummy untill E1.31 arrives
int channel_value_1 = 255; // update & dummy values for channel data
int channel_value_2 = 155; // update & dummy values for channel data
int channel_value_3 = 55; // update & dummy values for channel data
int channel_value_4 = 1; // update & dummy values for channel data

// general variables
long int num_channels; // number of DMX values in E1.31 packet
int loop_number = 255; // number of times too/looped
unsigned int step_ends; // single loop time value
//unsigned int step_delay = 30; // delay for 60Hz
unsigned int step_delay = 35; // delay for 50Hz

// E1.31 setup
const char ssid[] = "<SSID>"; // AP SSID
const char passphrase[] = "<password>"; // AP password
const int universe = 101; // universe number
const int channel_1 = 1; // output 1 channel number
const int channel_2 = 2; // output 2 channel number
const int channel_3 = 3; // output 3 channel number
const int channel_4 = 4; // output 4 channel number
E131 e131;

void setup() {
  // start serial
  Serial.begin(115200); // outputs - IP etc

  // set the function & state of the in / output pins
  pinMode(input_zc, INPUT); // set pin 4 as input
  pinMode(output_1, OUTPUT); // set pin 12 (D6) as output
  pinMode(output_2, OUTPUT); // set pin 13 (D7) as output
  pinMode(output_3, OUTPUT); // set pin 14 (D5) as output
  pinMode(output_4, OUTPUT); // set pin 16 (D0) as output
  pinMode(output_D, OUTPUT); // set pin 15 (D8) as output
  //  WRITE_PERI_REG(PERIPHS_IO_MUX_MTDO_U, READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U) & ~0x130);
  //  WRITE_PERI_REG(PERIPHS_IO_MUX_MTDO_U, READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U) | 0x30);



  //  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_ENABLE_ADDRESS, READ_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_ENABLE_ADDRESS) | 0xF000); // set gpio 12 -> 15 as outputs
  //  WRITE_PERI_REG(RTC_GPIO_ENABLE, READ_PERI_REG(RTC_GPIO_ENABLE) | 1);  // set gpio 16 as output
  pinMode(output_D, OUTPUT); // set pin 15 (D8) as output
  digitalWrite(output_1, HIGH);  // set output high / off
  digitalWrite(output_2, HIGH);  // set output high / off
  digitalWrite(output_3, HIGH);  // set output high / off
  digitalWrite(output_4, HIGH);  // set output high / off
  //  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS, 0xF000);  // set gpio 12 -> 15 output high / off
  //  WRITE_PERI_REG(RTC_GPIO_OUT, READ_PERI_REG(RTC_GPIO_OUT) | 1); // set gpio 16 output high
  digitalWrite(output_D, LOW);  // set output low / off

  // select unicast or multicast - one must be commented out
  //e131.begin(ssid, passphrase); // unicast
  e131.beginMulticast(ssid, passphrase, universe); // multicast
}

void loop() {
  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, 0x8000); // DEBUG LOW not part of finished code
  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS, 0x8000); // DEBUG HIGH not part of finished code
  num_channels = e131.parsePacket(); //if a new packet has arrived parse it
  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, 0x8000); // DEBUG LOW not part of finished code
  // do this if a new packet arrives
  if (num_channels) { // if a new packet has arrived - set new channel values
    channel_value_1 = (e131.data[channel_1]);  // update with value from E1.31 packet
    channel_value_2 = (e131.data[channel_2]);  // update with value from E1.31 packet
    channel_value_3 = (e131.data[channel_3]);  // update with value from E1.31 packet
    channel_value_4 = (e131.data[channel_4]);  // update with value from E1.31 packet
    step_ends += 870; // as we didn't look for the zero cross & set 'stop_ends' (don't have time to when a packet comes in)
    // use the value from the last loop and add some time to make the end time correct
  }
  else { // do this if NO new packet
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS, 0x8000); //DEBUG HIGH not part of finished code

    //    while (!(READ_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_IN_ADDRESS)& 0x10)); // loop untill zero cross pin goes high
    //    while (READ_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_IN_ADDRESS)& 0x10) { // loop untill zero cross pin goes low
    while (!digitalRead(input_zc));
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, 0x8000); // DEBUG LOW not part of finished code
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS, 0x8000); // DEBUG HIGH not part of finished code
    while (digitalRead(input_zc)) {
      step_ends = micros(); // set time to now - saves a little time doing it in this loop
    }
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, 0x8000); //DEBUG LOW not part of finished code
  }
  do {
    // switch on output / triac if we have waited long enough
    if (loop_number == channel_value_1)
      WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, 0x1000); // set output low / on
    if (loop_number == channel_value_2)
      WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, 0x2000); // set output low / on
    if (loop_number == channel_value_3)
      WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, 0x4000); // set output low / on
    if (loop_number == channel_value_4)
      WRITE_PERI_REG(RTC_GPIO_OUT, READ_PERI_REG(RTC_GPIO_OUT) & ~1); // set output low / on

    // wait untill it's time to loop & set the next outputs if required
    step_ends += step_delay; // add delay time to last end time to get new end time
    while (micros() < step_ends) { // check time now against end time & loop
      delay(0); // the magic delay - frees the processor to do some quick housekeeping, WiFi & stack stuff
    }
    loop_number--; // reduce loop counter by 1
  } while (loop_number > 0); // 'do' it all again unless ==0

  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS, 0xF000); // re-sets all outputs high as we are close to zero cross
  WRITE_PERI_REG(RTC_GPIO_OUT, READ_PERI_REG(RTC_GPIO_OUT) | 1); // set output high / on
  loop_number = 255; // re-set the value for loop counter ready for the next run
}


Should be quite easy to generate the WS2812b signal.
Code: Select allWRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS, <all GPIOs>); // set all high
delay();
WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, <some GPIOs>); // set 0s low leave 1s high
delay();
WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, <all GPIOs>); // set all low
delay();


Using the above a high - low for a '1' can be done in 83nS and a high - low for a '0' can be done in 166nS, so plenty fast enough. The slow part is returning to the start of the loop, from a '0' going low to the start of the next 'start' going high takes 3uS. You have 6uS to do this in, so not a problem but it doesn't leave you much processing time for data.