Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 14:39 02 May 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : equivalent of #define in mmbasic that does not consume variable space

     Page 1 of 2    
Author Message
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 04:41pm 29 Apr 2025
Copy link to clipboard 
Print this post

There is a mention of #define on page 103 in the CMM2LOAD but no explanation how it works

Reason : I'm running out of variables/constants. 256 is very little

I am talking to several devices that have large numbers of registers and parameters
i want to define constants for the register names and the value names so the code is readable.

instead of
I2C WRITE &H2C,01,&H24

do:
I2C WRITE DPCTRL0,1,TX1_EQUALIZER,EQU_DELAY_270PS

it would be nice if the define can contain actual code:
#define EQU_DELAY_270PS ((EQUALIZER and INV(&b01111000) OR (&b1010 <<3))
#define EQU_DELAY_330PS ((EQUALIZER and INV(&b01111000) OR (&b1011 <<3))
#define EQU_DELAY_380PS ((EQUALIZER and INV(&b01111000) OR (&b1100 <<3))
and nested:

#define DelayMask INV(&b01111000)
#define EQU_DELAY_270PS ((EQUALIZER and Delaymask) OR (&b1010 <<3))

these defines modify 4 specific bits in a register. The other bits have other functions
#define EQU_DELAY_DISABLE EQUALIZER and &b11111110
#define EQU_DELAY_ENABLE EQUALIZER or &b00000001
#define EQU_DELAY_OUTOFBOUND_ERROR (EQUALIZER AND &b10000000) >>7
Edited 2025-04-30 03:08 by vincenthimpe
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7464
Posted: 04:52pm 29 Apr 2025
Copy link to clipboard 
Print this post

CMM2LOAD is for loading a CMM2 program onto a different platform e.g. PicoMite. There is no need for it in many cases. The PicoMite can do it like this:

CONST DPCTRL0 = &H2C
CONST TX1_EQU_DELAY_270PS = &H24
.
.
I2C WRITE DPCTRL0,1,TX1_EQUALIZER,EQU_DELAY_270PS

As a full stop is accepted in a variable name you can use variables like this:

device1.input
device1.output
device1.something
device2.input
device2.output
device2.something

It might help with readability.

.
Edited 2025-04-30 02:55 by Mixtel90
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 05:25pm 29 Apr 2025
Copy link to clipboard 
Print this post

ah, good to know. but i'm still going to run out of variable space.

I need to shadow the data in the device since some registers cannot be read back. The read result is different from the write.

For example an ADC register:
- when read returns the ADC conversion result.
- when written contains the PGA scaling factor, a flag if it is single ended or differential and a flag if it is centered (-127 to 127) or unweighted (0 to 255)
a write operation triggers a conversion

so i need to retain the settings of these registers in the basic program

is there a limit to the number of constants a program can have ?
variable is limited to 256 on a rp2040
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7464
Posted: 05:30pm 29 Apr 2025
Copy link to clipboard 
Print this post

I think the figure of 256 is for variables and constants combined.

Ah - it's in the manual. Page 83.
The 2040 limit is 256.
The WebMite limit is 240.
The 2350 limit is 384.

When you use a LOCAL a normal variable is created then destroyed on exit unless STATIC so the limit is the same.
.
Edited 2025-04-30 03:37 by Mixtel90
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 05:47pm 29 Apr 2025
Copy link to clipboard 
Print this post

in my case the register names and datafields need to be global. They are definitions

256 is very little... I could write a number of custom functions but there too the limit is small.

i may have to rethink this and go back to a compiled language... but that is hard to debug interactively. i wanted something with an interactive way of working ( no NOT python ! that's the work of the devil )
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 1134
Posted: 05:48pm 29 Apr 2025
Copy link to clipboard 
Print this post

  Mixtel90 said  I think the figure of 256 is for variables and constants combined.

Ah - it's in the manual. Page 83.
The 2040 limit is 256.
The WebMite limit is 240.
The 2350 limit is 384.

When you use a LOCAL a normal variable is created then destroyed on exit unless STATIC so the limit is the same.
.


But does this mean we have 256/240/384 arrays at our disposal?
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7464
Posted: 05:56pm 29 Apr 2025
Copy link to clipboard 
Print this post

I would think so. It's one variable name per array, variable, string or constant. After that your limit is going to be the RAM available to store them. Watch the maximum number of dimensions for arrays to. It changes with platform.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7464
Posted: 06:01pm 29 Apr 2025
Copy link to clipboard 
Print this post

There will always be a limit on a small computer. :)  Even the RP2350 only has 512MB of RAM, which everything has to share.

You could re-use some variable names, packing 8 8-bit bytes into a single 64-bit integer between uses. You can also use a string to store numeric data - you just can't PRINT it.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 07:00pm 29 Apr 2025
Copy link to clipboard 
Print this post

  Mixtel90 said  There will always be a limit on a small computer. :)  Even the RP2350 only has 512MB of RAM, which everything has to share.

You could re-use some variable names, packing 8 8-bit bytes into a single 64-bit integer between uses. You can also use a string to store numeric data - you just can't PRINT it.


what good is 512K of ram if you can only define 256 variables. if all of these are integer or float (8byte per variable) you can use 2K of it....

It's not a matter of packing data. it's a matter of being able to define symbolic names for constants

I'm talking to a number of devices on I2c that have huge register maps (displayport multiplexer/retimer). I Want to define symbolic names for all its register so i don't have to delve into the datasheet all the time

I May have to get creative and define a lookup table as an array of strings.

dim Registers(240,2) length 10 as string

And have a function that seeks the "name" in column 1
column2 can hold a "string" containing 10 bytes (10 characters)

I can create a virtual map in there.

Let's say i have a 3 bit field in register 104 of an i2c slave at address 02c
the 10 bytes would contain :
i2caddress,register address,mask,invmask,shiftcount,initdata,currentdata,options

I can make a routine
CreateVirtualRegister ("SOMEREG",&h2c,104,3,4,7)
make a register in location 104 of a device at &h2c. it contains 3 bits and is offset by 4 bit. its default value is 7 : &b01110000  (2 bit offset/shifted by 4 bit)

That adds an entry in this table and builds the 10 byte string in column2.
A load/save routine can store and retrieve this table from drive a

then there is a read aand write routine

Writereg ("SOMEREG",3)
will alter that data to &b00110000. since it has all info stored in that magic 10 bytes it can do all bit and/or/shift operations under control of the magic string

Readreg ("SOMEREG") returns only the 3 bits as an integer. all masking and shifting has been done

my only problem is write only registers.... i may have to have a second table for those that shadows. or have a table for full "registers" and one for "fields"

Createregister "Somereg..."
Createfield "threebit","somereg"....

hmmm. i'd be sacrificing 20 bytes per register or field. And there would be an overhead in the routines since they need to search for the "key" but that's ok. speed and memory usage is irrelevant. even 1000 registers is only 20K. and there is 512K...

Interactivity is prime for this application.

What i'm making is an i2c chain debug tool. Define a map of devices, registers and fields and you can exercise at will. Either from command line or from basic code. I can store the entire framework as a library. i only need read,write,create and load + save functions

i like it. this solves the problems i have

Thanks !
Proven again that there's multiple ways to solve a problem
 
ville56
Senior Member

Joined: 08/06/2022
Location: Austria
Posts: 212
Posted: 07:01pm 29 Apr 2025
Copy link to clipboard 
Print this post

Good point, IMHO arrays could well be a solution for running out of variable namespace. The indices could be named with constants, so readability can be maintained quite well.
                                                                 
73 de OE1HGA, Gerald
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4244
Posted: 08:18pm 29 Apr 2025
Copy link to clipboard 
Print this post

If you've got a Pico 2 you can use #define if you start your program using CMM2 RUN.

See the CMM2 manual for #define syntax: https://geoffg.net/Downloads/Maximite/Colour_Maximite_2_User_Manual.pdf

Best wishes,

Tom
Edited 2025-04-30 06:18 by thwill
MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7464
Posted: 08:30pm 29 Apr 2025
Copy link to clipboard 
Print this post

You haven't got 512KB of RAM anyway. A chunk is used for MMBasic operations, including the variables table. Then you have any framebuffers for the video. In fact, the RAM area is so full that at runtime the user program runs from flash. It is only in RAM while it is being edited, at which time it is overwriting the area used for variables.

If you need a lot of space when using MMBasic then the CMM2 is the way to go, not the PicoMite. :)
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 09:02pm 29 Apr 2025
Copy link to clipboard 
Print this post

  Mixtel90 said  
If you need a lot of space when using MMBasic then the CMM2 is the way to go, not the PicoMite. :)


That's not a microcontroller... i want something small, near single chip. don't need video output and usb host.

Think 8051+ft232 small.

Rpi2040 is cheap and small with lots of i/o

That H7 processor is a humongous tqfp.
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3988
Posted: 10:07pm 29 Apr 2025
Copy link to clipboard 
Print this post

Maybe a compiled language such as C.

Or a preprocessor / transpiler - akin to Tom's (thwill).

Or a work-around as posted already.

For variables with MMBasic the RP2350 has more.

John
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2407
Posted: 10:17pm 29 Apr 2025
Copy link to clipboard 
Print this post

Another way to maintain readability without defining constants is with copious use of comments.
Prepare a text file with a list of the Const names you would have liked to use and their values.

Eg adapting Mick's list:-
'device1.input = &H12
'device1.output = &H34
'device1.something = &H56
'device2.input = &H78
'device2.output = &H9A
'device2.something = &HBC

Copy and paste from this list to the end of each line that needs them then copy the values into the line.

Its a bit more work but I have used it where maximum speed was needed rather than too many variables / constants.
All variables had to be reduced to one or two letters and no defined constants. It takes time for the interpreter to read each character, and even longer to lookup values. It was the only way to keep track.
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3299
Posted: 11:39pm 29 Apr 2025
Copy link to clipboard 
Print this post

  vincenthimpe said  That H7 processor is a humongous tqfp.


Maybe you would want to look at the STM32F407VGT6 Development Board:

https://www.aliexpress.com/item/1005006882009420.html



If you go that way, make sure you order the VGT6 version.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 03:07am 30 Apr 2025
Copy link to clipboard 
Print this post

  JohnS said  Maybe a compiled language such as C.

That's exactly what i DON'T want to use. I want something interactive, BASIC is perfect for that. Python is to restrictive. You are more busy aligning text than doing actual work.

Basic is very forgiving in syntax. Not case sensitive, doesn't care about whitespace, no curly braces, semicolons and it knows when = means assign and when compare. in short : it's ideal for what i do. The endless compile, fix a bug compile again gets old very quickly.

Note: I write C code for non-hobby. Mainly HAL and BSP drivers. But that is on processors for which there are IDE's with in-circuit debugger/tracers so i can set breakpoints, watchpoints and alter memory during runtime.

Thanks for the suggestion anyway.
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 03:34am 30 Apr 2025
Copy link to clipboard 
Print this post

  phil99 said  Another way to maintain readability without defining constants is with copious use of comments.
Prepare a text file with a list of the Const names you would have liked to use and their values.

Eg adapting Mick's list:-
'device1.input = &H12
'device1.output = &H34
'device1.something = &H56
'device2.input = &H78
'device2.output = &H9A
'device2.something = &HBC

Copy and paste from this list to the end of each line that needs them then copy the values into the line.


That's not the goal.

The goal is to define all these elements and be able to call from the command line without needing an actual program

type a command and use the symbolic names directly. it's not just an entire register. i want to access individual fields within a register.

For example : an ADC control register is 8 bits with the following layout:
bit7 : ADCstart : write to 1 to start conversion, if cleared conversion is done
bit 6:5 : Programmable gain amplifier control x1 x2 x5 x10
bit 4   : single ended or differential input
bit 3   : signed/unsigned result
bit 2:0 : averaging count

this is 1 register at address 0x22 on an i2c device at 0x2c

i want to make a mechanism that allows me to twiddle bits without overwriting others.

' register name, i2c address, register address)
Createregister (ADCcontrol , 0x2c,0x22)
CreateRegister (ADCresultreg,0x2c,0x23)

' valuename, registername, mask,shiftcount,bitlength)
CreateValue (ADCstart,ADCcontrol,&b1000000,7,1)
Createvalue (ADCgain,ADCcontrol,&b01100000,5,2)
Createvalue (ADCSingleDiff,ADCccontrol,&b00010000,4,1)
Createvalue (ADCSignUnsign,ADCcontrol,&b00001000,3,1)
Createvalue (ADCaverage,ADCcontrol,&b00000111,0,3)
CreateValue (ADCresult,ADCresultreg,&b11111111,0)


now i can do things like

Set ADCgain,2
Set ADCaverage,4
Set ADCSingleDiff ,1
Set ADCStart,1

while get(ADC) = 1
wend
result = Get(ADCresult)

without having to look up anything. Everything is defined as constants or variables.
I'll run out of storage very quickly.
In a real compiled language such tables are not a problem.

My workaround now is using a single 2 dimensional array. Essentially a keypair.
the key is the name of the register (or value), the paired string is used as a bytestring that stores the mapping

So the createregister and Createvalue add entries in the table, the Set and Get functions look up a given "key" , retrieve the attached definition and perform the i2c operations, bit masking and shifting up/down. A write operations does a fetch first to get register contents, apply new fields and write back ( read,modify,write).

i may have to come up with a mechanism for write only registers so i can shadow what is there.

Maybe an additional parameter
Createregister (ADCcontrol , 0x2c,0x22,<type>) where type is 1,2 or 3 ( 2 bits, one for Read, one for write) if a register is type 2 (write only) it creates an index in an additional table to store the shadow data information.


What i am making is a debugging tool to very quickly (with a minimum amount of keyboard hammering) be able to excercise i2c devices ( more than one device on the bus).

I can generate the register tables from code. ( my i2c devices reside in an FPGA and i have already made a tool to spit out register definitions in verilog and c code so i can easily spit out another syntax.)

This is intended to be a debug tool to hook into a bus and excercise register contents without requiring compilation. Load the definitions and have interactive control and make little subroutines.

The tables can be stored as a CSV file in the A drive. A simple routine can load them into the arrays.

So i have a workaround. all i need is 3 global arrays (one for registers,one for variables,one for shadowing write-onlies). the rest are some simple functions that i can store as a library and become an extention of MMBasic.
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 03:35am 30 Apr 2025
Copy link to clipboard 
Print this post

  lizby said  
  vincenthimpe said  That H7 processor is a humongous tqfp.


Maybe you would want to look at the STM32F407VGT6 Development Board:

can it run MMBasic ?
Even then. i'm rolling my own board. (there lots of other stuff i need)
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3988
Posted: 06:31am 30 Apr 2025
Copy link to clipboard 
Print this post

  vincenthimpe said  
  lizby said  
  vincenthimpe said  That H7 processor is a humongous tqfp.


Maybe you would want to look at the STM32F407VGT6 Development Board:

can it run MMBasic ?

Yes

Lots of threads on STM32F4 CPUs and Armmite

Also on https://fruitoftheshed.com/wiki/doku.php?id=start

Various STM32 boards etc are supported.

John
 
     Page 1 of 2    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025