ULP - 32 bits arithmetics

matheusmbg
Posts: 10
Joined: Thu Feb 20, 2020 2:44 pm

ULP - 32 bits arithmetics

Postby matheusmbg » Thu Feb 20, 2020 3:01 pm

Hello guys,

I need to interface HX711 with ESP32 in deep sleep mode. That shouldn't be a problem because interfacing with HX711 is really simple, just putting some pins up, some pins down and read some pins and do some basic math.

The biggest challenge i'm facing right now is to work with 32 bits variable. At some point of the code i need to shift 1 bit left, and thats really hard to do because all 4 registers are 16 bits only. I'm having trouble right now at the line "jump b_lsb_1, 0x8000". Compiler gives me this error : "Jump adress is to far. Input text was eq.".

Code is below and i haven't finished yet, i'm trying to do part by part. If someone could please give me some advice of a easiest way to work with 32 bits variables on ULP or even a easiest way to interface HX711 with ULP ESP32, i would be very pleased.
PS: Sorry 4 PT-BR comments in the code :lol: , the parts that i have doubts are commented in english :D
Thank u very much,
Matheus

#include "soc/soc_ulp.h"
#include "soc/rtc_io_reg.h"
#include "soc/sens_reg.h"
#include "soc/rtc_cntl_reg.h"


.bss//Variaveis sao declaradas dentro da secao .bss

.global measurement_count
measurement_count: .long 0

.text//O codigo é feito dentro da secao .text

.global main
main://O codigo e iniciado aqui, equivale ao void setup()

jump loop
loop: //add0 = 9 adsk = 8
WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S+9, 1, 1)//sobe add0
WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//desce adsk
le_add0:
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 9, 1) // le gpio_num_15 = rtc gpio 13
and r0, r0, 1 // faz uma and do valor lido com 0x01
jumpr le_add0, 0, eq // se o valor de r0 for igual zero, volta para ler dnv r0
stage_rst
loop_count:
WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//desce adsk
and r0, r1, 0x8000 // R0 = R1 & 0X8000
jumpr b_lsb_1, 0x8000, // if R1 (LSB BYte) MSB BIT is 1, R0 will be equal to 0x8000 then jump to b_lsb_1
jump b_lsb_0 // if R1(LSB Byte) MSB bit is 0, R0 will be 0x0000
b_lsb_0: // R1 MSB Bit equal 0
lsh r0, r1, 1 // shift 1 bit left from LSB Byte
mov r1, r0
lsh r0, r2, 1 // shift 1 bit left from R2( MSB Byte)
mov r2, r0
jump loop_count
b_lsb_1: // R1 MSB Bit equal 0
lsh r0, r1, 0x01 // shift 1 bit left from lsb byte
mov r1, r0
lsh r0, r2, 0x01 // shift 1 bit left from msb byte
add r2, r0, 1 // add 1 to the value that correspondsto MSB bit from LSB byte that now is LSB bit of MSB Byte.
jump loop_count

boarchuz
Posts: 604
Joined: Tue Aug 21, 2018 5:28 am

Re: ULP - 32 bits arithmetics

Postby boarchuz » Thu Feb 20, 2020 7:26 pm

Use two registers. Or if 16 bit resolution is enough, read 16 bits in and just clock the rest.

matheusmbg
Posts: 10
Joined: Thu Feb 20, 2020 2:44 pm

Re: ULP - 32 bits arithmetics

Postby matheusmbg » Fri Feb 21, 2020 7:14 pm

Any idea on how can i read this 32 bits variable, that i got using ULP, in my main app? I have MSB byte in one register and LSB byte in another register. I need to get these two values in one 32 bits variable.

boarchuz
Posts: 604
Joined: Tue Aug 21, 2018 5:28 am

Re: ULP - 32 bits arithmetics

Postby boarchuz » Sat Feb 22, 2020 3:27 am

uint32_t val = (ulp_msb << 16) | (ulp_lsb & 0xFFFF);

matheusmbg
Posts: 10
Joined: Thu Feb 20, 2020 2:44 pm

Re: ULP - 32 bits arithmetics

Postby matheusmbg » Fri Nov 13, 2020 9:03 pm

Hello guys, reliving this old topic. I sucessed on reading HX711 with ULP coprocessor. I achieve this a few days later my post here, but i completely forgot to post the code for those who may need to do this in future. Since ULP is a small processor, i tought easier to work just with the 24 bits decimal value read from HX711, instead of converting this decimal value to weight and then analysing the value. The system wake up if the value read from HX711 is higher than a threshold (that is calculated by main processor equivalent to an weight threshold). The comments are in portuguese, but i guess google translator can translate it easily :)

Code: Select all

#include "soc/soc_ulp.h"
#include "soc/rtc_io_reg.h"
#include "soc/sens_reg.h"
#include "soc/rtc_cntl_reg.h"

.data

						.global trshHoldADMSB
trshHoldADMSB: .long 0x00
						.global trshHoldADLSB
trshHoldADLSB: .long 0x00

.bss//Variaveis sao declaradas dentro da secao .bss

                        .global bytelsb
bytelsb:       .long 0
                        .global bytemsb
bytemsb:       .long 0
						.global valorADMSB
valorADMSB:    .long 0
						.global valorADLSB
valorADLSB:    .long 0
						.global debugVar
debugVar:      .long 0
						.global contador
contador:  	   .long 0
						.global MediaZeroTaraMSB
MediaZeroTaraMSB: .long 0

						.global MediaZeroTaraLSB
MediaZeroTaraLSB: .long 0
.text//O codigo é feito dentro da secao .text
 
	.global main
	main://O codigo e iniciado aqui, equivale ao void setup()
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S+12, 1, 1)//sobe add0

 		jump loop
	loop: //add0 = 9 adsk = 8
		move r3, 0x00
		move r1, bytelsb
		st r3, r1, 0
		move r3, 0x00
		move r2, bytemsb
		st r3, r2, 0
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S+9, 1, 1)//sobe add0
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//desce adsk
	le_add0:
		READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 9, 1) // le gpio_num_15 = rtc gpio 13
		and r0, r0, 1 // faz uma and do valor lido com 0x01
		jumpr le_add0, 1, eq // se o valor de r0 for igual 1, volta para ler dnv add0
		stage_rst
	loop_count:
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//sobe adsk
		move r1, bytelsb
		ld r1, r1, 0
		move r2, bytemsb
		ld r2, r2, 0
		move r1, bytelsb
		ld r1, r1, 0
		move r2, bytemsb
		ld r2, r2, 0
		and r0, r1, 0x8000 // R0 = R1 & 0X8000
		jumpr b_lsb_1, 32767, gt// if R1 (LSB BYte) MSB BIT is 1, R0 will be greater than 32767 then jump to b_lsb_1
	b_lsb_0: // R1 MSB Bit equal 0
		move r0, r1
		lsh r0, r0, 1 // shift 1 bit left from LSB Byte
		move r1, bytelsb
		st r0, r1, 0
		move r0, r2
		lsh r0, r0, 1 // shift 1 bit left from MSB Byte
		move r2, bytemsb
		st r0, r2, 0
		jump inc_count
	b_lsb_1: // R1 MSB Bit equal 1
		move r0, r1
		lsh r0, r0, 0x01 // shift 1 bit left from lsb byte
		move r1, bytelsb
		st r0, r1, 0
		move r0, r2
		lsh r0, r0, 0x01 // shift 1 bit left from msb byte
		add r0, r0, 1 // add 1 to the value corresponding to MSB bit from LSB byte that now is LSB bit of MSB Byte.
		move r2, bytemsb
		st r0, r2, 0
	inc_count:
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//desce adsk
		READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 9, 1) // le gpio_num_15 = rtc gpio 13
		and r0, r0, 1 // faz uma and do valor lido com 0x01
		jumpr fim_loop, 0, eq // se o valor de r0 for igual zero significa q gpio esta baixo então n incrementa r1
		move r1, bytelsb
		ld r0, r1, 0
		add r0, r0, 1
		jump ovflw_soma, ov
		move r3, bytelsb
		st r0, r3, 0
		jump fim_loop
	ovflw_soma:
		move r3, bytelsb
		st r0, r3, 0
		move r3, bytemsb
		ld r0, r3, 0
		add r0, r0, 1
		st r0, r3, 0
	fim_loop:
		stage_inc 1
		jumps loop_count, 24, lt
 	xor:
		move r2, bytemsb
		ld r2, r2, 0
 		WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//sobe adsk
		and r3,r2,0x0080
  		or r0,r2,0x0080
 		sub r0,r0,r3
  		sub r0,r0,r3
  		move r2, r0
  		move r3, valorADMSB
  		st r2, r3, 0
  		move r3, valorADLSB
  		move r1, bytelsb
		ld r1, r1, 0
		st r1, r3, 0
		//lsb nao precisa de xor já que o valor feito o xor em 32bits é 0x00800000, portanto todo o LSB seria feito o xor com 0x00
		// em que o resultado é igual a entrada.
	fim:
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//desce adsk
	compair_trshHold:
		move r2, trshHoldADMSB
		ld r2, r2, 0
		move r3, valorADMSB
		ld r3, r3, 0
		sub r0, r2, r3
		jumpr msb_igual, 0, eq
		jump wake_up, ov // overflow significa que r3 > r2 portanto vloadAD > threshHold
		// msb ad menor q threshhold
		move r3, debugVar
		move r0, 0x05
		st r0, r3, 0
		jump loop
	msb_igual:
		move r3, debugVar
		move r0, 0x07
		st r0, r3, 0
		move r2, trshHoldADLSB
		ld r2, r2, 0
		move r3, valorADLSB
		ld r3, r3, 0
		sub r0, r2, r3
		move r1, contador
		st r0, r1, 0
		jump wake_up, ov // overflow significa que r3 > r2 portanto vloadAD > threshHold
		jump loop

	wake_up:
		move r3, debugVar
		move r0, 0x06
		st r0, r3, 0
		/* Check if the system can be woken up */
		READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)

		and r0, r0, 1
		jump loop, eq

		/* Wake up the SoC, end program */
		wake
		WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
		halt

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: ULP - 32 bits arithmetics

Postby PeterR » Fri Nov 13, 2020 9:23 pm

May be missing the difficulty but:
ntoh/hton
This seams an endian issue.
& I also believe that IDF CAN should be fixed.

lot-ion
Posts: 1
Joined: Fri Jul 08, 2022 5:50 am

Re: ULP - 32 bits arithmetics

Postby lot-ion » Fri Jul 22, 2022 3:08 am

matheusmbg wrote:
Fri Nov 13, 2020 9:03 pm
Hello guys, reliving this old topic. I sucessed on reading HX711 with ULP coprocessor. I achieve this a few days later my post here, but i completely forgot to post the code for those who may need to do this in future. Since ULP is a small processor, i tought easier to work just with the 24 bits decimal value read from HX711, instead of converting this decimal value to weight and then analysing the value. The system wake up if the value read from HX711 is higher than a threshold (that is calculated by main processor equivalent to an weight threshold). The comments are in portuguese, but i guess google translator can translate it easily :)

Code: Select all

#include "soc/soc_ulp.h"
#include "soc/rtc_io_reg.h"
#include "soc/sens_reg.h"
#include "soc/rtc_cntl_reg.h"

.data

						.global trshHoldADMSB
trshHoldADMSB: .long 0x00
						.global trshHoldADLSB
trshHoldADLSB: .long 0x00

.bss//Variaveis sao declaradas dentro da secao .bss

                        .global bytelsb
bytelsb:       .long 0
                        .global bytemsb
bytemsb:       .long 0
						.global valorADMSB
valorADMSB:    .long 0
						.global valorADLSB
valorADLSB:    .long 0
						.global debugVar
debugVar:      .long 0
						.global contador
contador:  	   .long 0
						.global MediaZeroTaraMSB
MediaZeroTaraMSB: .long 0

						.global MediaZeroTaraLSB
MediaZeroTaraLSB: .long 0
.text//O codigo é feito dentro da secao .text
 
	.global main
	main://O codigo e iniciado aqui, equivale ao void setup()
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S+12, 1, 1)//sobe add0

 		jump loop
	loop: //add0 = 9 adsk = 8
		move r3, 0x00
		move r1, bytelsb
		st r3, r1, 0
		move r3, 0x00
		move r2, bytemsb
		st r3, r2, 0
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S+9, 1, 1)//sobe add0
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//desce adsk
	le_add0:
		READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 9, 1) // le gpio_num_15 = rtc gpio 13
		and r0, r0, 1 // faz uma and do valor lido com 0x01
		jumpr le_add0, 1, eq // se o valor de r0 for igual 1, volta para ler dnv add0
		stage_rst
	loop_count:
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//sobe adsk
		move r1, bytelsb
		ld r1, r1, 0
		move r2, bytemsb
		ld r2, r2, 0
		move r1, bytelsb
		ld r1, r1, 0
		move r2, bytemsb
		ld r2, r2, 0
		and r0, r1, 0x8000 // R0 = R1 & 0X8000
		jumpr b_lsb_1, 32767, gt// if R1 (LSB BYte) MSB BIT is 1, R0 will be greater than 32767 then jump to b_lsb_1
	b_lsb_0: // R1 MSB Bit equal 0
		move r0, r1
		lsh r0, r0, 1 // shift 1 bit left from LSB Byte
		move r1, bytelsb
		st r0, r1, 0
		move r0, r2
		lsh r0, r0, 1 // shift 1 bit left from MSB Byte
		move r2, bytemsb
		st r0, r2, 0
		jump inc_count
	b_lsb_1: // R1 MSB Bit equal 1
		move r0, r1
		lsh r0, r0, 0x01 // shift 1 bit left from lsb byte
		move r1, bytelsb
		st r0, r1, 0
		move r0, r2
		lsh r0, r0, 0x01 // shift 1 bit left from msb byte
		add r0, r0, 1 // add 1 to the value corresponding to MSB bit from LSB byte that now is LSB bit of MSB Byte.
		move r2, bytemsb
		st r0, r2, 0
	inc_count:
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//desce adsk
		READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 9, 1) // le gpio_num_15 = rtc gpio 13
		and r0, r0, 1 // faz uma and do valor lido com 0x01
		jumpr fim_loop, 0, eq // se o valor de r0 for igual zero significa q gpio esta baixo então n incrementa r1
		move r1, bytelsb
		ld r0, r1, 0
		add r0, r0, 1
		jump ovflw_soma, ov
		move r3, bytelsb
		st r0, r3, 0
		jump fim_loop
	ovflw_soma:
		move r3, bytelsb
		st r0, r3, 0
		move r3, bytemsb
		ld r0, r3, 0
		add r0, r0, 1
		st r0, r3, 0
	fim_loop:
		stage_inc 1
		jumps loop_count, 24, lt
 	xor:
		move r2, bytemsb
		ld r2, r2, 0
 		WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//sobe adsk
		and r3,r2,0x0080
  		or r0,r2,0x0080
 		sub r0,r0,r3
  		sub r0,r0,r3
  		move r2, r0
  		move r3, valorADMSB
  		st r2, r3, 0
  		move r3, valorADLSB
  		move r1, bytelsb
		ld r1, r1, 0
		st r1, r3, 0
		//lsb nao precisa de xor já que o valor feito o xor em 32bits é 0x00800000, portanto todo o LSB seria feito o xor com 0x00
		// em que o resultado é igual a entrada.
	fim:
		WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S+8, 1, 1)//desce adsk
	compair_trshHold:
		move r2, trshHoldADMSB
		ld r2, r2, 0
		move r3, valorADMSB
		ld r3, r3, 0
		sub r0, r2, r3
		jumpr msb_igual, 0, eq
		jump wake_up, ov // overflow significa que r3 > r2 portanto vloadAD > threshHold
		// msb ad menor q threshhold
		move r3, debugVar
		move r0, 0x05
		st r0, r3, 0
		jump loop
	msb_igual:
		move r3, debugVar
		move r0, 0x07
		st r0, r3, 0
		move r2, trshHoldADLSB
		ld r2, r2, 0
		move r3, valorADLSB
		ld r3, r3, 0
		sub r0, r2, r3
		move r1, contador
		st r0, r1, 0
		jump wake_up, ov // overflow significa que r3 > r2 portanto vloadAD > threshHold
		jump loop

	wake_up:
		move r3, debugVar
		move r0, 0x06
		st r0, r3, 0
		/* Check if the system can be woken up */
		READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)

		and r0, r0, 1
		jump loop, eq

		/* Wake up the SoC, end program */
		wake
		WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
		halt
Have anyone tested the code yet? I have tried it so far but, i got a constantly reset loop between wakeup caused by ULP and sleep.
I set up trshHoldADLSB to 54464 and trshHoldADMSB to 128 then the reset loop disappeared. Unfortunately, when the thing (probably 500gr) is put on the scale. It won't wake up.

I thought do I miss understanding which variable I should set to put the threshold value in, but again, I don't have an experience yet with assembly language.

Who is online

Users browsing this forum: No registered users and 76 guests