![]() |
Forum Index : Microcontroller and PC projects : equivalent of #define in mmbasic that does not consume variable space
![]() ![]() |
|||||
Author | Message | ||||
PhenixRising Guru ![]() Joined: 07/11/2023 Location: United KingdomPosts: 1133 |
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 KingdomPosts: 9992 |
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 KingdomPosts: 1133 |
![]() |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7458 |
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 StatesPosts: 45 |
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 KingdomPosts: 7458 |
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 StatesPosts: 45 |
That's the mechanism i will use. store my functions as a library |
||||
vincenthimpe Regular Member ![]() Joined: 14/10/2018 Location: United StatesPosts: 45 |
$#@% 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: AustraliaPosts: 2407 |
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: AustraliaPosts: 963 |
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 StatesPosts: 45 |
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) |
||||
![]() ![]() |
![]() |