BAS.POKE in ESP8266

Here we can discuss about the problem found
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Re: BAS.POKE in ESP8266

Post by Fernando Perez »

Thanks Robin, but your proposal is another way (with another programming style) to achieve the same thing I want to avoid.
You could also have used DATA and READ or mid$:

Code: [Local Link Removed for Guests]

gpio$ = "00010203040512131415"
for i = 1 to len(gpio$) step 2
  gpio = val(mid$(gpio$, i, 2))
  pin.mode gpio, output
next i
But understand that what I am looking for is to emulate the way in which in PICs or AVRs the pins of a complete port were configured as inputs and/or outputs simply by writing what was desired in a memory register.
And I ask the desert: Is it not possible with ESPs?
User avatar
cicciocb
Site Admin
Posts: 2060
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 439 times
Been thanked: 1358 times
Contact:

Re: BAS.POKE in ESP8266

Post by cicciocb »

Fernando,
if I understand well you want modify all the IO bits "at the same time" like you do in an x bits port.

First of all you must define the pins that you want use ....
each pin is associated with a specific bit of the ports.

It is not really easy to do, at least in basic, because the bits are not all free and contiguous.

The bit association is simple as the registers are 32 bits but only the first 16 bits are used.
So
bit 0 ->GPIO0
bit 1 ->GPIO1
bit 2 ->GPIO2
......
bit15 ->GPIO15

The GPIO16 is handled differently so you can avoid to use it.

The rule between GPIO and bits can be written as:

Code: [Local Link Removed for Guests]

binary_value = 1 << bit
So, for the GPIO0, the value is

Code: [Local Link Removed for Guests]

binary_value = 1 << 0
And, for the GPIO15, the value is

Code: [Local Link Removed for Guests]

binary_value = 1 << 15
Now, because you want use the pins 0, 1, 2, 3, 4, 5, 12, 13, 14, 15
you must isolate bit per bit, compose the complete binary word and then write in a one shoot.

let's say that you want write a word included in a variable LEDS.
This variable contains 10 bits where each bit controls a led
Let's say that
the bit 0 is connected to the pin 0
the bit 1 is connected to the pin 1
the bit 2 is connected to the pin 2
the bit 3 is connected to the pin 3
the bit 4 is connected to the pin 4
the bit 5 is connected to the pin 5
the bit 6 is connected to the pin 12
the bit 7 is connected to the pin 13
the bit 8 is connected to the pin 14
the bit 9 is connected to the pin 15

To do that you must do something as below :

Code: [Local Link Removed for Guests]

LEDS = &b1010101010
x = LEDS
val = 0
val = val or ((x and 1) << 0
x = x >> 1
val = val or ((x and 1) << 1
x = x >> 1
val = val or ((x and 1) << 2
x = x >> 1
val = val or ((x and 1) << 3
x = x >> 1
val = val or ((x and 1) << 4
x = x >> 1
val = val or ((x and 1) << 5
x = x >> 1
val = val or ((x and 1) << 12
x = x >> 1
val = val or ((x and 1) << 13
x = x >> 1
val = val or ((x and 1) << 14
x = x >> 1
val = val or ((x and 1) << 15
at the end, the variable val will contain the value that you can write in the final register as below:

Code: [Local Link Removed for Guests]

GPIO_ENABLE_SET = &H60000310
GPIO_OUT   = &H60000300 
GPIO_IN   = &H60000318 

'define the output mask bits
mask = &b1111000000111111  ' pins 0,1,2,3,4,5,12,13,14,15
bas.poke GPIO_ENABLE_SET , mask  ' each bit=1 means output

'and finally, you can write the word in the output (but you must read the previous value before)
prev = bas.peek(GPIO_IN)
'mask the bits that you don't want change
prev = (prev and &h111111000000)
'compose the final word
bas.poke GPIO_OUT , prev or val
AS you can see, it seems a little bit complicate to do in basic; probably should be much easy in C.

One of the big problems when trying to play with the registers is that the CHIP can do other tasks in the background (in particular the ESP32) so, it is probable that the value read from the input can change during the execution time of the interpreted line of code.
BeanieBots
Posts: 345
Joined: Tue Jun 21, 2022 2:17 pm
Location: South coast UK
Has thanked: 183 times
Been thanked: 112 times

Re: BAS.POKE in ESP8266

Post by BeanieBots »

I guess it really comes down to why you want to do this.
If it's to make the code more elegant, then I think you are on to a loser :cry:
If it is to avoid delays between each bit changing then the only solution would be to add another bit of hardware such as a shift register (perhaps an I2C version) and send it a binary map of the desired output. That would also give you the benefit of more IO to play with.
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Re: BAS.POKE in ESP8266

Post by Fernando Perez »

Francesco, thanks for your explanation and your example. By the way, very educational.
I have deduced that it is not possible to establish at the beginning of the program, and permanently during its execution, the pins that we want to function as input and output. It seems that every time we are going to send a value of zero or one to some pins, we must declare those pins as output, find out the previous value of all pins and, once masked, perform the actual writing. Truly, it seems complicated.
But there is a problem. I have loaded your example program on my ESP8266 (correcting the &h on line 12 with &b) and when I run it, my LEDs persist in staying off. Except GPIO2, which even with my code lights up dimly at first, since the ESP8266 has an internal resistor connected to GND on that pin.

Now please analyze this code, which I have reduced to a minimum so as not to bore you :oops: , and watch the video:

Code: [Local Link Removed for Guests]

dim led(9) = 0, 1, 2, 3, 4, 5, 12, 13, 14, 15
for i = 0 to 9
  pin.mode led(i), output
next i

do
  for i = 0 to 1023
    pinOUT i
    pause 50
  next i
  pause 250
  pinOUT 0
  pause 3000
loop

END

' -----------------------------
SUB pinOUT(adress)
LOCAL ofset
  ofset = (adress\64) * 4032
  BAS.POKE &H60000300, adress + ofset
END SUB
https://youtube.com/shorts/Y98_Yzdi5Xw?feature=share

It works perfectly, without faltering or showing errors during the several hours that I have been running it.
The difference: I use the traditional method of establishing the GPIOS configuration using pin.mode. I suspect, therefore, that what fails is the system of doing it through records.
Since it is not a problem to do so and I was simply curious to know the internal workings of the ESP, I beg your pardon and I thank you for the time you have dedicated to me.
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Re: BAS.POKE in ESP8266

Post by Fernando Perez »

BeanieBots, effectively my goal is that on the 10 useful pins of my ESP8266 now, and on the more than 10 useful pins of my ESP32 in the future, a given binary value appears instantly.
For example, to manage a 2114 RAM memory or a Z80 microprocessor. According?
Greetings.
BeanieBots
Posts: 345
Joined: Tue Jun 21, 2022 2:17 pm
Location: South coast UK
Has thanked: 183 times
Been thanked: 112 times

Re: BAS.POKE in ESP8266

Post by BeanieBots »

As a great fan of both Z80 and static CMOS RAM myself, I would suggest to simply set the IO accordingly even if sequencially and then excert the appropriate R/W/CE line. If that is not an option for your setup then use something like a 74LS244 or similar octal buffer and clock it through.
User avatar
cicciocb
Site Admin
Posts: 2060
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 439 times
Been thanked: 1358 times
Contact:

Re: BAS.POKE in ESP8266

Post by cicciocb »

[Local Link Removed for Guests] wrote: [Local Link Removed for Guests]Thu Nov 23, 2023 9:46 am Francesco, thanks for your explanation and your example. By the way, very educational.
I have deduced that it is not possible to establish at the beginning of the program, and permanently during its execution, the pins that we want to function as input and output. It seems that every time we are going to send a value of zero or one to some pins, we must declare those pins as output, find out the previous value of all pins and, once masked, perform the actual writing. Truly, it seems complicated.
But there is a problem. I have loaded your example program on my ESP8266 (correcting the &h on line 12 with &b) and when I run it, my LEDs persist in staying off. Except GPIO2, which even with my code lights up dimly at first, since the ESP8266 has an internal resistor connected to GND on that pin.

Now please analyze this code, which I have reduced to a minimum so as not to bore you :oops: , and watch the video:

Code: [Local Link Removed for Guests]

dim led(9) = 0, 1, 2, 3, 4, 5, 12, 13, 14, 15
for i = 0 to 9
  pin.mode led(i), output
next i

do
  for i = 0 to 1023
    pinOUT i
    pause 50
  next i
  pause 250
  pinOUT 0
  pause 3000
loop

END

' -----------------------------
SUB pinOUT(adress)
LOCAL ofset
  ofset = (adress\64) * 4032
  BAS.POKE &H60000300, adress + ofset
END SUB
https://youtube.com/shorts/Y98_Yzdi5Xw?feature=share

It works perfectly, without faltering or showing errors during the several hours that I have been running it.
The difference: I use the traditional method of establishing the GPIOS configuration using pin.mode. I suspect, therefore, that what fails is the system of doing it through records.
Since it is not a problem to do so and I was simply curious to know the internal workings of the ESP, I beg your pardon and I thank you for the time you have dedicated to me.
Fernando,
if you want understand how it works internally, the best is to look at the code in the ESP8266 SDK (it is C).

To do what you want do, the best should be to implement a function PORT(x) where all the bits can be defined previously but ,honestly I don't think it worth to continue the development on the ESP8266.
User avatar
Electroguard
Posts: 860
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 276 times
Been thanked: 323 times

Re: BAS.POKE in ESP8266

Post by Electroguard »

I didn't realise before that you were trying to write all output bits in one word Fernando... your masochism makes more sense now.
And my late understanding is probably way off the mark, but I'll mention it anyway...

When I was doing something similar last century using ports, having set up the required port bits for outputs, I avoided needing to read existing values of all port bits each time, by keeping the output word 'write' value to use as an exclusive OR (EXOR) mask for just changing new port bits with, then kept that new exor'd write result for the next mask etc, so the only port bits that were changed each time were those that were different from the last write.
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Re: BAS.POKE in ESP8266

Post by Fernando Perez »

Thank you very much to the three of you and for my part, I consider the topic closed, since with my last code I believe I have achieved the objective. Although my logic analyzer is only 8 channels, the pins I connect show wonderful square waves synchronized enough for what I need.
Although I'm afraid I'll bother you again when I transfer it to the ESP32.
Meanwhile, the parade of LEDs at a binary rhythm continues to fascinate me as before!
bugs
Posts: 143
Joined: Mon Feb 08, 2021 10:10 pm
Location: Scotland
Has thanked: 47 times
Been thanked: 51 times

Re: BAS.POKE in ESP8266

Post by bugs »

It has been an interesting thread. I did attempt to understand the ESP register section 2.2 but struggled when it seemed you had to write to two different registers depending on whether you wanted a bit set or cleared.
Just before you go - could you post the working code for enlightenment... :)
Post Reply