-->
Page 1 of 2

GPIO out help

PostPosted: Fri Mar 06, 2015 9:58 am
by folny82
Hello friends

Please help with GPIO outputs seeks to add 4 GPIO outputs to control ws2812 pixels me managed to add outputs GPIO0 and GPOI2 is working properly but I would need to add additional 2 outputs GPIO13 and GPIO14 please can someone advise how to do it thanks.

here is the code

#include "osapi.h"
#include "ets_sys.h"

#define GPIO_OUTPUT_SET(gpio_no, bit_value) gpio_output_set(bit_value<<gpio_no, ((~bit_value))<<gpio_no, 1<<gpio_no,0)

void ICACHE_FLASH_ATTR SEND_WS_0()
{
uint8_t time;
time = 4; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR , 0x1 );
time = 9; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR , 0 );
}

void ICACHE_FLASH_ATTR SEND_WS_1()
{
uint8_t time;
time = 8; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR , 0x1 );
time = 6; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR , 0 );
}

void ICACHE_FLASH_ATTR SEND_WS_2()
{
uint8_t time;
time = 4; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR , 0x4 );
time = 9; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR , 0 );
}

void ICACHE_FLASH_ATTR SEND_WS_3()
{
uint8_t time;
time = 8; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR , 0x4 );
time = 6; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR , 0 );
}

void ICACHE_FLASH_ATTR ws2812_strip1(uint8_t * buffer, uint16_t length)
{
uint16_t i;

GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0);

os_intr_lock();
for( i = 0; i < length; i++ )
{
uint8_t mask = 0x80;
uint8_t byte = buffer[i];
while (mask)
{
( byte & mask ) ? SEND_WS_1() : SEND_WS_0();
mask >>= 1;
}
}
os_intr_unlock();
}

void ICACHE_FLASH_ATTR ws2812_strip2(uint8_t * buffer, uint16_t length)
{
uint16_t i;

GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);

os_intr_lock();
for( i = 0; i < length; i++ )
{
uint8_t mask = 0x80;
uint8_t byte = buffer[i];
while (mask)
{
( byte & mask ) ? SEND_WS_3() : SEND_WS_2();
mask >>= 1;
}
}
os_intr_unlock();
}

void ICACHE_FLASH_ATTR ws2812_init()
{
ets_wdt_disable();
char outbuffer[] = { 0x00, 0x00, 0x00 };
ws2812_strip1( outbuffer, sizeof(outbuffer) );
ws2812_strip2( outbuffer, sizeof(outbuffer) );
}

Re: GPIO out help

PostPosted: Fri Mar 06, 2015 11:13 am
by EadF
First of all you should include "gpio.h" since you are using gpio_output_set()
Relying on, pre C99, implicitly declared functions is always of source of hard to find bugs. Imho

Then to set GPIO13 and GPIO14 as outputs you need to do this in your ws2812_init():
(actually it enables the pins as gpios, setting as outputs is done by GPIO_OUTPUT_SET)

PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); //GPIO13
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,FUNC_GPIO14); //GPIO14


I have never tested without it, but i always call gpio_init() in my user_init() for good measure.

Re: GPIO out help

PostPosted: Fri Mar 06, 2015 11:48 am
by folny82
EadF wrote:First of all you should include "gpio.h" since you are using gpio_output_set()
Relying on, pre C99, implicitly declared functions is always of source of hard to find bugs. Imho

Then to set GPIO13 and GPIO14 as outputs you need to do this in your ws2812_init():
(actually it enables the pins as gpios, setting as outputs is done by GPIO_OUTPUT_SET)

PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); //GPIO13
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,FUNC_GPIO14); //GPIO14


I have never tested without it, but i always call gpio_init() in my user_init() for good measure.


Thank you for the advice but do not know yet how to define the outputs of these lines, for example, to set the GPIO13

void ICACHE_FLASH_ATTR SEND_WS_2()
{
uint8_t time;
time = 4; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR ...
time = 9; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR ...
}

void ICACHE_FLASH_ATTR SEND_WS_3()
{
uint8_t time;
time = 8; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR ...
time = 6; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR ...
}

Re: GPIO out help

PostPosted: Fri Mar 06, 2015 12:45 pm
by EadF
You can take a look at how cnlohr did the same thing:
Code: Select allvoid SEND_WS_0()
{
  uint8_t time = 8;
  WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
  WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
  while(time--)
  {
    WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
  }
}
void SEND_WS_1()
{
  uint8_t time = 9;
  while(time--)
  {
    WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
  }
  time = 3;
  while(time--)
  {
    WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
  }
}


To send to another gpio pin you change the value of WSGPIO in your new methods:
SEND_WS_13_0(), SEND_WS_13_1(), SEND_WS_14_0() and SEND_WS_14_1()

(The SEND_WS_* methods sends binary data to the ws2812, so naming them SEND_WS_2, SEND_WS_3 was too confusing for me :) )

But you will still have to call the PIN_FUNC_SELECT function i described above (and GPIO_OUTPUT_SET) to set up the pin properly.

Usually it's enough to just use GPIO_OUTPUT_SET(pin,value) to set a gpio, but the ws2812 is very picky with exact timings.

Disclamer: I have not tested this, and i'm unfamiliar with WRITE_PERI_REG for gpio stuff. But in cnlohr we trust.


EDIT: hm.. I'm not so sure that WRITE_PERI_REG really work this way. Disregard my reply (i'm going to double check this)