Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 14:43 01 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 2 of 2    
Author Message
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 1133
Posted: 07:02am 30 Apr 2025
Copy link to clipboard 
Print this post

  vincenthimpe said  

That H7 processor is a humongous tqfp.


There's more than one version of the H7. The WeAct is the 100-pin version. I LOVE these things  


 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9992
Posted: 07:06am 30 Apr 2025
Copy link to clipboard 
Print this post

All modern versions of MMbasic (Armmite, CMM2, PicoMite etc.) have an explicit limit on the number of variables and constants use a variable slot - this is based on the size of the variable hash table. The MM2 and MM+ don't have this limitation, other than memory, but large numbers of variables will cause the code to grind to a halt as they use sequential search to find a variable.
The CMM2 also has a limit on the number of #defines as does the CMM2 compatibility mode on the PicoMite.
This is something you will have to live with.
Alternatively, you could write a pre-processor to take a program with a large number of constants/defines and replace them with literals before loading to MMBasic
Edited 2025-04-30 17:07 by matherp
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 1133
Posted: 07:32am 30 Apr 2025
Copy link to clipboard 
Print this post

  matherp said  
Alternatively, you could write a pre-processor to take a program with a large number of constants/defines and replace them with literals before loading to MMBasic



 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7458
Posted: 07:40am 30 Apr 2025
Copy link to clipboard 
Print this post

Re. the CMM2 being a computer. Erm...

The ARM Cortex M7 cores are designed for embedded processing and that's what the CMM2 uses. It's basically the definition of microcontrollers. Ok, the CMM2 is more powerful and expandable but that's one of the big differences between that and the Pico (The Pico 2 is using dual ARM Cortex M33 cores). It's pretty safe to think of the PicoMite as a cut-down CMM2 now - they share a lot of firmware code. The CMM2 is no more a "proper" computer than the PicoMite is really, it still doesn't have an OS.

The CMM2 will give you 512 LOCAL variables plus 512 GLOBAL variables.
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:10pm 30 Apr 2025
Copy link to clipboard 
Print this post

Again, that is not the intent i have.
i don't want to write a program. i want to use MMbasic essentially as a command parser.

Using the command prompt i call functions directly without needing a "run" command.
Just like you can type "print 1+2" hit enter and you get 7 , i want to make a system where i can write "Get ADCreturn" and it replies 44 (or whatever). The "constant" ADCreturn defines a location inside an i2c device.

if i want to make a "script" i can still make a real program and run it, or call functions from the command line, or store it as a library and call from the command prompt.

Most compiled languages have a #define - like statement. for interpreters that is more difficult. That's where constants come into play.

Anyway i have it solved (i think). i will just make my own lookup table in the form of an array of strings. Find the passed string in the table, retrieve the associated string and use the byte function to unpack it into the configuration data.

Yes, it will take time to process but i don't care. Flexibility is what i am after.

Debugging complex i2c devices with hundreds of registers and busses with multiple of these devices is difficult. Even if you have oscilloscopes with pattern decoding and logic analyzers. You can read , but you can't write.
And you still only get "address 44 on device 19 contains 27". But what does that mean ? Doing a read-modify-write is also cumbersome as i need to do the work.

The device i am creating will unwrap this further and tell me :
ADCpga = 4 , ADCSinDiff = 1, ADCready = 1, ADVavg = 9

I Want bus mastering capability so i can not only examine contents but also alter them. This is a debugging tool to assist software development. To break the endless compile, run , doesn't work, alter compile again cycle because i'm setting some registers wrong. I can use this interactive tool to play with the register contents.
i can also use it to dump the contents of a working system. Take a working device that uses the chip, power it up, hold the bus controller in reset and dump the bus to see how they configured the registers.


Since i'm storing the register and field definitions in a table i can make small programs that can dump the entire table an get a full report

for x 1 to Registers
 print Register(x,0) ; " : " ; Get Registers(x,0)
next
for x 1 to Fields
 print Field(x,0) ; " : " ; Get Field(x,0)
next


Will print me the register or field name followed by its contents.

print get("ADCavg")
set ("ADCavg",7)


I know this is a very specialized tool i'm building and may not appeal to many people.

anyway all that aside :

It just surprises me that the number of constants and variables is so low. Even a commodore 64 did not have a limit to the number of variable definitions . Same for gwbasic in the ibm rom. Same for 8051-ah-basic .That one was limited to the first and last letter of a variable name. Peep and Poop would point to the same variable. Still 26x36 possibilities.Can't start with number so only 26 start letters , but can end in a number so 36 letter+digit (PA..PZ,P0,...P9,QA and so on) They tokenized the names internally to two characters. When you listed the program they de-tokenized so your variable name wasn't lost, but the interpreted code used the tokens.

I'm treating the pico with mmbasic as a small instant-on basic computer. Hook up a terminal and go.
I Do not want to use a compiler as this stuff needs to work dynamically and be alterable on the fly, so i need an interpreter. why reinvent the interpreter wheel...
(modern) Basic is perfectly fine as an interpreter. I could use micropythong or circuitpython but i'd be more busy swearing at the text alignment and mistakes against =/== than doing work.

Storing the definitions in an array also has the advantage i can save/restore the array to a file.
 
Mixtel90

Guru

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

I think it's probably a swap. You can have space for an unlimited number of variables, but they will be slow to look up so the program speed suffers. MMBasic uses a hash table which minimizes the lookup time, but you have to accept a maximum size for the table.

RAM space on the Pico is precious, especially on the RP2040. It's also split into blocks on the internal bus, and is paged in and out as required. It's not contiguous memory.

The MMBasic platforms are *not* computers, they just look as if they are "boot to BASIC" home computers. You can think of it as an emulation. There is no underlying OS to handle commands or a file system, everything is done either from a console connection which is used for system setup and control (this has no direct access to variables etc.) or from within a running program. In fact, unlike the computers that they emulate, there is no defined UPA (user program area). The program is either running from flash or copied over the variables area for editing. RUN moves it into flash.

The Commodore 64 was also limited to 26*36=936. That system requires some imaginative variable naming though! You get 31-character names in MMBasic, with all characters valid.

From the command line you can't run program routines unless the program has been RUN first. That moves the program from RAM to flash, where it can be executed. There is an exception though. Routines in the Library *can* be run directly from the command line without RUN. That's because they already exist in flash slot 3 and are never in RAM.
Edited 2025-05-01 04:36 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: 10:14pm 30 Apr 2025
Copy link to clipboard 
Print this post

  Mixtel90 said  
The MMBasic platforms are *not* computers,
[quote]
i know that. i did a lot of work using the 8052-ah-basic. trying to do something similar with a cheapo micro with embedded basic: rpi2040 + mmbasic


[quote]
The Commodore 64 was also limited to 26*36=936. That system requires some imaginative variable naming though!
[/quote]
interesting... didn't know that. 8052 used the same trick.

[quote] Routines in the Library *can* be run directly from the command line without RUN. That's because they already exist in flash slot 3 and are never in RAM.


That's the mechanism i will use. store my functions as a library
 
vincenthimpe
Regular Member

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

$#@% the trick doesn't work.

variables are stored on the heap.
if i do this :

dim a(1,1) as string length 10

i would expect it to allocate 40 bytes + some overhead : the array holds 4 strings, each 10 bytes long.

but, it consumes over 1k.

So it does not make strings of 10 characters. it still consumes 255 bytes per string. The "length" parameter is not respected.

dim integer regs(2048) grabs 16K off the heap, which is to be expected since every integer consumes 8 bytes.

if i use 4 integers per "register" i can store a 16 character long "name" in the first 2 integers and have the next 2 integers to store the bit twiddling info (device address, register address, masking and shifting information. i could probably do it as 3 integers for the name (would allow me 24 characters. i could even compress the register names as i would only need 6 bits to store a letter/number so i can load 10 characters per integer and one integer to hold the twiddling info.

i'll have my own heap on top of the heap to store my stuff . LOL

that's in essence what longstrings are. so i can exploit that mechanism and use the Byte read/write from the longstring functions to manipulate the array.
Edited 2025-05-01 09:00 by vincenthimpe
 
phil99

Guru

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

  Quote  dim a(1,1) as string length 10
...So it does not make strings of 10 characters. it still consumes 255 bytes per string. The "length" parameter is not respected.
Yes and No.
If memory serves, when Length is 7 or less 8 bytes of memory are allocated (the first allocated byte of a string holds the number of characters used).
When Length is more than 7 256 bytes of memory are allocated, but you can't use more than Length characters. So as far as the program or command line is concerned Length is respected.

Edit.
That the 7 or less case isn't applied to multiples of 8 bytes probably means it would be difficult to implement.
Edited 2025-05-01 10:22 by phil99
 
disco4now

Guru

Joined: 18/12/2014
Location: Australia
Posts: 963
Posted: 02:55am 01 May 2025
Copy link to clipboard 
Print this post

  vincenthimpe said  $#@% the trick doesn't work.

dim a(1,1) as string length 10

i would expect it to allocate 40 bytes + some overhead : the array holds 4 strings, each 10 bytes long.

but, it consumes over 1k.

So it does not make strings of 10 characters. it still consumes 255 bytes per string. The "length" parameter is not respected.



Try one of these syntax. LENGTH should be immediately after the variable name.

DIM a(4,3) LENGTH 10 AS STRING
or
DIM STRING a(4,3) LENGTH 10
or
DIM a$(4,3) LENGTH 10

This fits within 256 bytes and only allocates 256 bytes. The granularity I think is 256 byte chunks but only as many as you really need.
Latest F4 Latest H7 FotS
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 45
Posted: 03:50am 01 May 2025
Copy link to clipboard 
Print this post

  disco4now said  

Try one of these syntax. LENGTH should be immediately after the variable name.

DIM a(4,3) LENGTH 10 AS STRING
or
DIM STRING a(4,3) LENGTH 10
or
DIM a$(4,3) LENGTH 10

This fits within 256 bytes and only allocates 256 bytes. The granularity I think is 256 byte chunks but only as many as you really need.


Yes, that works. Curious it doesn't throw a syntax error

Anyway, i already migrated to an array of integers with packed names. 4 integers allow me to store the register name and all associated data to find it.
I can also instantiate multiple copies of the same device

CreateDevice("IOCTRL1","PCA9585",0x72)
CreateDevice("IOCTRL2","PCA9585",0x74)
 
     Page 2 of 2    
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2025