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

BAS.POKE in ESP8266

Post by Fernando Perez »

I have assembled the device that can be seen in the video to demonstrate that 10 LEDs can be perfectly managed controlling 10 GPIOS of the ESP8266.
This is the program:

Code: [Local Link Removed for Guests]

' For ESP8266 Wemos D1 Mini
' GPIO0=D3 : GPIO1=TX : GPIO2=D4 : GPIO3=RX : GPIO4=D2 : GPIO5=D1
' GPIO12=D6 : GPIO13=D7 : GPIO14=D5 : GPIO15=D8 : GPIO16=D0 

' DECLARE SUB display(w, l)
' Turns on or off the corresponding bit of the decimal value w for a width of l bits.

' DECLARE SUB dec_bin(w, l)
' Display decimal value w in binary format, adding leading zeros until full width l.

dim led(9) = 0, 1, 2, 3, 4, 5, 12, 13, 14, 15

' Declares all 10 pins as output and sets them to zero
for n = 0 to 9
  pin.mode led(n), output
  pin(n) = 0
next n

pause 5000

t= 80 ' scroll speed in milliseconds

' DOT SCROLL:
for n = 0 to 10
  w = 2^(n-1)
  display w, 10
  dec_bin w, 10
  pause t
next n

for n = 10 to 0 step -1
  w = 2^(n-1)
  display w, 10
  dec_bin w, 10
  pause t
next n

pause 500

'BAR SCROLL:
for n = 0 to 10
  w = (2^n)-1
  display w, 10
  dec_bin w, 10
  pause t
next n  

pause 200

for n = 10 to 0 step -1
  w = (2^n)-1
  display w, 10
  dec_bin w, 10
  pause t
next n  

pause 500

' Opening and closing bar:
dim patern(5) = 0, 513, 771, 903, 975, 1023
for n = 1 to 3
  for i = 0 to 5
    w = patern(i)
    display w, 10
    pause t
  next i
  for i = 5 to 0 step -1
    w = patern(i)
    display w, 10
    pause t
  next i
next n  
pause 500

' BINARY COUNTER:
for w = 0 to 1023
  display w, 10
  dec_bin w, 10
  pause 50
next w  

display 0, 10

END

' ---------------
SUB display(w, l)
LOCAL bit
  for bit = 0 to l-1
  if (w and (1 << bit)) <> 0 then pin(led(bit))=1 else pin(led(bit))=0
  next bit
END SUB
' ---------------
SUB dec_bin(w, l)
LOCAL b$
  b$ = bin$(w)
  b$ = string$(l-len(b$), "0") + b$
  wlog b$
END SUB    

And this is the video:
https://youtube.com/shorts/9CxZwJHE0O0?feature=share

But my goal is to ask you for help on a question. If I replace the "normal" GPIO control instructions with what I thought were equivalent for BAS.POKE, I have a problem.

Code: [Local Link Removed for Guests]

DIR_OUTPUT = &H60000310
GPIO_OUT   = &H60000300 

'PIN_IN     = &H60000318
'GPIO_SET   = &H60000304
'GPIO_ENABLE = &H6000030C

t = 1500
           
BAS.POKE8 DIR_OUTPUT, &B00001111

bas.poke8 GPIO_OUT, &B0000
pause t
bas.poke8 GPIO_OUT, &B0001
pause t
bas.poke8 GPIO_OUT, &B0010
pause t
bas.poke8 GPIO_OUT, &B0011
pause t
bas.poke8 GPIO_OUT, &B0100
pause t
bas.poke8 GPIO_OUT, &B0101
pause t
bas.poke8 GPIO_OUT, &B0110
pause t
bas.poke8 GPIO_OUT, &B0111
pause t
bas.poke8 GPIO_OUT, &B1000
pause t
bas.poke8 GPIO_OUT, &B1001  ' Fail
pause t
bas.poke8 GPIO_OUT, &B1010
pause t
bas.poke8 GPIO_OUT, &B1011  ' Fail
pause t
bas.poke8 GPIO_OUT, &B1100
pause t
bas.poke8 GPIO_OUT, &B1101  ' Fail
pause t
bas.poke8 GPIO_OUT, &B1110
pause t
bas.poke8 GPIO_OUT, &B1111  ' Fail
pause t

bas.poke8 GPIO_OUT, &B0001  ' Ok
pause t

END

LED 1 does not light up from line 30 of this program:

https://youtube.com/shorts/WDUk2gRwEXw?feature=share

Please, what am I doing wrong?
User avatar
Electroguard
Posts: 860
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 274 times
Been thanked: 323 times

Re: BAS.POKE in ESP8266

Post by Electroguard »

I noticed your syntax highlighting does not seem to properly recognise your esp8266 bas.poke8 instructions, whereas my esp32 1.51.3 does highlight
So maybe try running your same script on an esp32 (with pin numbers adjusted) and just wlog the changes of pin status, rather than hooking up leds.
It could prove a point, and isolate where the problem is.

poke.jpg
You do not have the required permissions to view the files attached to this post.
User avatar
cicciocb
Site Admin
Posts: 2056
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 439 times
Been thanked: 1355 times
Contact:

Re: BAS.POKE in ESP8266

Post by cicciocb »

Most of the registers of the chip must be accessed at 32 bits (and not at 8 bits as you are doing).

THis is an example from the help (That I'm not sure if I published :? )

Code: [Local Link Removed for Guests]

'EXAMPLE SHOWING THE USE OF PEEK AND POKE FOR BLINKING LEDS
'-------------------------------------------------------------
'Name Description Address Access
'#define ESP8266_REG(addr) *((volatile uint32_t *)(0x60000000+(addr)))
'//GPIO (0-15) Control Registers
'#define GPO    ESP8266_REG(0x300) //GPIO_OUT R/W (Output Level)
'#define GPOS   ESP8266_REG(0x304) //GPIO_OUT_SET WO
'#define GPOC   ESP8266_REG(0x308) //GPIO_OUT_CLR WO
'#define GPE    ESP8266_REG(0x30C) //GPIO_ENABLE R/W (Enable)
'#define GPES   ESP8266_REG(0x310) //GPIO_ENABLE_SET WO
'#define GPEC   ESP8266_REG(0x314) //GPIO_ENABLE_CLR WO
'#define GPI    ESP8266_REG(0x318) //GPIO_IN RO (Read Input Level)
'#define GPIE   ESP8266_REG(0x31C) //GPIO_STATUS R/W (Interrupt Enable)
'#define GPIES  ESP8266_REG(0x320) //GPIO_STATUS_SET WO
'#define GPIEC  ESP8266_REG(0x324) //GPIO_STATUS_CLR WOWO
'-------------------------------------------------------------
pin.mode 4, output
pin.mode 5, output
do
  pin(4) = 0
  pin(5) = 0
  print bin$(bas.peek(&h60000300))
  pause 1000
  pin(4) = 1
  pin(5) = 1
  print bin$(bas.peek(&h60000300))
  pause 1000
  bas.poke &h60000308, &b110000
  print bin$(bas.peek(&h60000300))
  pause 1000
  bas.poke &h60000304, &b110000
  print bin$(bas.peek(&h60000300))
  pause 1000
loop

edit :
additionally, if my memory still works properly, the GPIO16 is even different as it is handled by another block of registers.
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. Thinking about your advice not to use LEDs, I remembered that I have (in a dusty box) an 8-channel logic analyzer, a Saleae clone, and I obtained this screen:

https://www.myrapidq.it/public/Saleae8.png
I'll spend some time tonight. I no longer remember how to use it.

Francesco, your memory is correct, the GPIO16 is completely separate, but in my final project I will use it for something else.
You had not published that code, at least I can't find it, but I only have access to version 1.43 of the ESP8266 help.
MY fear when using 32-bit access is that in the ESP8266 gpios 6 to 11 SHOULD NOT BE TOUCHED and I understand that with GPIO_OUT all the bits are written. Can it interfere with prohibited addresses?
I guess I should use GPIO_OUT_SET, GPIO_OUT_CLR and masks instead, but I don't dare.
User avatar
cicciocb
Site Admin
Posts: 2056
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 439 times
Been thanked: 1355 times
Contact:

Re: BAS.POKE in ESP8266

Post by cicciocb »

Check the datasheet of the esp8266 but these registers must be read and write at 32 bits. You must use the set and reset registers to change only the bits you want.
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 »

Is working. It was enough to use, as you said, BAS.POKE instead of BAS.POKE8.
I have managed to control all 10 GPIOS with this system. And, for now, I do not detect interference or operating problems with the ESP8266 module despite writing zeros to GPIOS 6 to 11. Perhaps they are write protected.
It has been difficult for me to calculate the formula for the ofset that omits these addresses, but it seems to work well.
And I have managed to avoid using set and reset because I do not want to divide the direct writing to the register into two different instructions. It would mean that for a moment, even if it is minimal, an unwanted value appears at the outputs.
Like always, thank you.

P.S. Peter, I'm preparing my Z80s.

Code: [Local Link Removed for Guests]

DIR_OUTPUT = &H60000310
GPIO_OUT   = &H60000300 
BAS.POKE DIR_OUTPUT, &B111111111111111

t = 50
for i = 0 to 1023
  ofset = (i\64) * 4032
  adress = i + ofset
  bas.poke GPIO_OUT, adress
  pause t
  gosub binZero
next i

pause 3000
bas.poke GPIO_OUT, 0

END

binZero:
  i$ = str$(i)
  i$ = string$(4-len(i$), " ") + i$

  ofset$ = str$(ofset)
  ofset$ = string$(5-len(ofset$), " ") + ofset$

  b$ = bin$(bas.peek(GPIO_OUT))
  b$ = string$(16-len(b$), "0") + b$
  b$ = mid$(b$, 1, 4) + " " + mid$(b$, 5, 6) + " " + mid$(b$, 11, 6)
  wlog i$, ofset$, b$

return
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 »

To avoid changing bits you don't want to change, first do a PEEK then mask (or set accordingly) the relevant bits before pokeing.
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, BeanieBots, that was my first intention. But, surprisingly, I have seen that the operation of the ESP8266 does not seem to be altered despite writing zeros in positions GPIO6 to GPIO11.
So, why bother using two or three instructions when it works satisfactorily with one?

My next experiment is to replace the ESP8266 with an ESP32 and expand the outputs to 20 pins. I suppose I can use the same offset system since the ESP32 also does not have GPIOS 6 to 11 available (it seems to me).
And vary the memory address of DIR_OUTPUT and GPIO_OUT, which on the ESP32 I am not yet very clear about what they are.
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 »

Well no, I have seen that my program does not work as I expected.

Code: [Local Link Removed for Guests]

' ============================
'GPIO_ENABLE      = &H6000030C
'GPIO_ENABLE_W1TS = &H60000310
'GPIO_ENABLE_W1TC = &H60000314
GPIO_OUT         = &H60000300
'GPIO_OUT_W1TC    = &H60000308
'GPIO_OUT_W1TS    = &H60000304
'=============================

'BAS.POKE GPIO_ENABLE, &HF03F

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

for i = 0 to 1023
  pinOUT i
  displayOut i
  pause 100
next i

pause 3000

pinOUT 0

END

' -----------------------------
SUB pinOUT(adress)
LOCAL ofset
  ofset = (adress\64) * 4032
  BAS.POKE GPIO_OUT, adress + ofset
END SUB

' -----------------------------
SUB displayOUT(adress)
LOCAL a$, b$

  a$ = str$(adress)
  a$ = string$(4-len(a$), " ") + a$

  b$ = bin$(bas.peek(GPIO_OUT))
  b$ = string$(16-len(b$), "0") + b$
  b$ = mid$(b$, 1, 4) + " " + mid$(b$, 5, 6) + " " + mid$(b$, 11, 6)

  wlog a$, b$

END SUB  
My desire was to replace the instructions dedicated to configuring all the GPIOS of the ESP8266 as output (lines 12 to 16) with a single BAS.POKE instruction, writing the desired value in the appropriate register.
But it does not work. I have tried various combinations (GPIO_ENABLE = &H6000030C and GPIO_ENABLE_W1TS = &H60000310) to no avail.
Until I execute lines 12 to 16, the program does not illuminate the LEDs.
I have reviewed the attached documentation, but I don't know how to follow it.
Does anyone know how to do it? I know it may seem like a whim, but if it involves configuring more than 20 pins using the traditional method, the work is worth it.
You do not have the required permissions to view the files attached to this post.
User avatar
Electroguard
Posts: 860
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 274 times
Been thanked: 323 times

Re: BAS.POKE in ESP8266

Post by Electroguard »

When you say 'Whim', I hear 'masochism'.

Whatever you decide to do, you will need a list of valid usable output pins to avoid messing with addressing, but no need to read into an array though.
You could just parse a list of text pin numbers, which might be chosen according to the esp device being used, eg:
(I haven't ran this BTW, was just an idea off the top of my head)

Code: [Local Link Removed for Guests]

esp$ = "8266"
select case esp$
case "8266": pinlist$ = "0,1,2,3,4,5,12,13,14,15"
case "S2":   pinlist$ = "(list of valid S2 output pins)"
case "S3":   pinlist$ = "(list of valid S3 output pins)" 
case "Z9":   pinlist$ = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,22,33,44,55,66,77,88,99"
'etc
case else:   pinlist$ = "2"
end select
'everything above is only to highlight the advantage of doing it as below...

for pin = 1 to word.count(pinlist$)
 gpio = val(word$(pinlist$, pin, ","))
 pin.mode gpio, output ': pin(gpio) = 0  '(to optionally set a default)
next pin

'you might even extend it to set up inputs as well as outputs by prefixing inputs with minus or whatever
Post Reply