![]() |
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 StatesPosts: 45 |
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 KingdomPosts: 7464 |
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 StatesPosts: 45 |
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 KingdomPosts: 7464 |
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 StatesPosts: 45 |
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 KingdomPosts: 1134 |
But does this mean we have 256/240/384 arrays at our disposal? |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7464 |
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 KingdomPosts: 7464 |
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 StatesPosts: 45 |
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: AustriaPosts: 212 |
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 KingdomPosts: 4244 |
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 KingdomPosts: 7464 |
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 StatesPosts: 45 |
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 KingdomPosts: 3988 |
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: AustraliaPosts: 2407 |
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 StatesPosts: 3299 |
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 StatesPosts: 45 |
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 StatesPosts: 45 |
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 StatesPosts: 45 |
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 KingdomPosts: 3988 |
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 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |