Menu
JAQForum Ver 19.10.27

Forum Index : Microcontroller and PC projects : PicoMite V6.02.00 release candidates - Structured types

   Page 7 of 9    
Posted: 09:20am
11 Jan 2026
Copy link to clipboard
matherp
Guru

  Quote  I had simply expected the interrupt for TX-Fifo to be empty on a regular basis. But it is not deterministic?!


From the MMBasic manual
  Quote  The TX interrupt triggers whenever the specified FIFO has been FULL and the
PIO code has now "pulled" it


I've explained this before, the interrupt allows you to feed the PIO at maximum rate. It tells you there is now a space in the fifo. It does not interrupt UNLESS the fifo has been full and now isn't
Edited 2026-01-11 19:20 by matherp
 
Posted: 11:03am
11 Jan 2026
Copy link to clipboard
Volhout
Guru

@Peter,

I fully understand where the confusion around the TX interrupt comes from.

When you look from ARM standpoint, the TX interrupt implementation is sound. The ARM runs at similar or higher frequency as the PIO, and can usew the interrupt to push the FIFO constantly full to the limits. This using the TX interrupt to take action.

When executing MMBasic statements, the PIO is typically faster to read the data from FIFO than MMBasic can supply data. Hence the FIFO may never achieve FULL. You write 1 data element, but PIO has already taken one out. You never reach FULL, so you never get a TX interrupt.
The TX interrupt is therefore not really usable for this purpose. Not for individual data elements.

I have no idea if a better implementation is possible.

In this case I would not rely on an interrupt, but use PIO (LEVEL ) to see how much would fit, and write that into FIFO in one PIO WRITE. And repeat this in a loop. If you insist on using interrupts, then execute this in a SETTICK controlled interrupt loop.

But it is far better to not put this "refill" responsibility on MMBasic level. Use DMA,that is safer. Look at the implementations like the HUB75 driver. Earlier versions used individual DMA's, later versions us a DMA RING BUFFER.

Volhout
Edited 2026-01-11 21:08 by Volhout
 
Posted: 11:26am
11 Jan 2026
Copy link to clipboard
matherp
Guru

  Quote  When executing MMBasic statements, the PIO is typically faster to read the data from FIFO than MMBasic can supply data.

Could be useful for something like serial output or I2C but I agree there are other (better?) ways depending on the application. The facility is there to be used or not as the MMbasic prefers.
 
Posted: 01:17pm
11 Jan 2026
Copy link to clipboard
homa
Guru


Yes, the TX interrupt is really confusing. @Peter: I already understood that, but I'm trying to fully grasp it and create an example for it. However, it is a very special case in which the interrupt is only triggered. Volhout describes the problem surrounding it. I would classify it as a racing condition. I can't explain it any better than that.
Thanks for your efforts.
I have decided to learn and understand the interaction between PIO and MMBasic.

Another question that concerns me is: Can I write only 8 bits to the FIFO? Or always only a 32-bit value? It would be really helpful not to always have to write a 32-bit value. Or to assemble it beforehand from four 8-bit values. In addition, a gap of n x 8-bit zeros is created when I want to add values. As I said, I'm still learning. With the DMA solution, I saw that you can specify this appropriately in memory reading.
The manual also states the following for PIO WRITE:  

PIO WRITE pio, state_machine, count, data0 [,data1..]
Writes the data elements to the pio and state machine specified. The write is
blocking so the state machine needs to be able to take the data supplied
NB: this command will probably need additional capability in future releases


Addendum:
I will answer myself as best I can. Currently, I can only write 32-bit values in FIFO. An update is not planned, as the value may be pulled at that moment and the bit pointer would have to be manipulated/updated. Is that even possible?
So, do I have to ensure in PIO that the remaining 24 bits are discarded or ignored if I want 8-bit/1-byte values?
Edited 2026-01-12 00:40 by homa
 
Posted: 06:47pm
11 Jan 2026
Copy link to clipboard
Volhout
Guru

Hi Homa,

PIO does not have to use the 32 bits. A pull instruction copies 32 bits in OSR, but the PIO program or configuration decides how many bits it uses.

So write a byte to FIFO (24 bits waste, 8 used), and in the PIO program decide to only use 8 bits (using the OUT instruction, with destination GPIO or X or Y or...).

An alternative could be to PACK multiple 8 bit values in 32 bits, and write a PIO program that uses. Search the manual for PACK.

.label return_here
 PULL
 OUT 8 bits (the first 8)
 OUT 8 bits
 OUT 8 bits
 OUT 8 bits
JMP return_here

Volhout

P.S. there are provisions to automate this. You can set the threshold how many bits are shifted out of OSR (i.e. 17) when an automatic PULL happens, and the OSR is overwritten. You could use this threshold at 8, and use it to transfer bytes, but the value written in FIFO must be a 32 bit value. That is hardware.
Edited 2026-01-12 04:51 by Volhout
 
Posted: 07:01pm
12 Jan 2026
Copy link to clipboard
Sasquatch
Guru


Found an "error" in the GPS_parse function in the GPS.c source file.  If the NMEA checksum is missing, the message passes the checksum test.  The attached GPS.c file will discard the NMEA message if the checksum "*" delimiter is missing.


GPS.zip
 
Posted: 12:12pm
13 Jan 2026
Copy link to clipboard
matherp
Guru

V6.02.00RC5

PicoMiteV6.02.00RC5.zip

Improves error handling of pre-processor errors - things like duplicate function names. These will now give the same sort of message as a program error and position the cursor when entering the editor

Fixes GPS as per Sasquatch's message

Re-engineers SELECT CASE to avoid memory issues. If you use SELECT CASE please test thoroughly.

Adds the SUN as a valid body in commands ASTRO and STAR (RP2350 only)

GPS_Astro_Reference.pdf

My select case test program
' SELECT CASE Memory Test Program
' Tests temp memory cleanup with many CASE statements
' Matches at positions: 5, 50, 100, 150, 199, and CASE ELSE

OPTION EXPLICIT

DIM test%, pass%, fail%
pass% = 0
fail% = 0

PRINT "SELECT CASE Memory Test"
PRINT "========================"
PRINT

' Test 1: Match early (position 5)
test% = 1
PRINT "Test 1: Match at position 5... ";
SelectTest("case005")
IF pass% <> 1 THEN fail% = fail% + 1 : PRINT "FAIL" ELSE PRINT "PASS"

' Test 2: Match at position 50
test% = 2
pass% = 0
PRINT "Test 2: Match at position 50... ";
SelectTest("case050")
IF pass% <> 1 THEN fail% = fail% + 1 : PRINT "FAIL" ELSE PRINT "PASS"

' Test 3: Match at position 100
test% = 3
pass% = 0
PRINT "Test 3: Match at position 100... ";
SelectTest("case100")
IF pass% <> 1 THEN fail% = fail% + 1 : PRINT "FAIL" ELSE PRINT "PASS"

' Test 4: Match at position 150
test% = 4
pass% = 0
PRINT "Test 4: Match at position 150... ";
SelectTest("case150")
IF pass% <> 1 THEN fail% = fail% + 1 : PRINT "FAIL" ELSE PRINT "PASS"

' Test 5: Match at position 199 (near end)
test% = 5
pass% = 0
PRINT "Test 5: Match at position 199... ";
SelectTest("case199")
IF pass% <> 1 THEN fail% = fail% + 1 : PRINT "FAIL" ELSE PRINT "PASS"

' Test 6: No match - should hit CASE ELSE
test% = 6
pass% = 0
PRINT "Test 6: CASE ELSE (no match)... ";
SelectTest("nomatch")
IF pass% <> 2 THEN fail% = fail% + 1 : PRINT "FAIL" ELSE PRINT "PASS"

' Test 7: Run multiple times to check for memory leaks
PRINT
PRINT "Test 7: Repeated calls (100x) to check memory...";
DIM i%
FOR i% = 1 TO 100
 SelectTest("case100")
NEXT i%
PRINT " PASS"

' Test 8: Integer SELECT CASE with many options
PRINT "Test 8: Integer SELECT with 200 cases... ";
pass% = 0
SelectTestInt(150)
IF pass% <> 1 THEN fail% = fail% + 1 : PRINT "FAIL" ELSE PRINT "PASS"

PRINT
PRINT "========================"
PRINT "Tests complete. Failures: " + STR$(fail%)
PRINT
PRINT "Check MEMORY command for heap usage"
MEMORY

END

SUB SelectTest(val$)
 LOCAL result$
 result$ = ""
 
 SELECT CASE val$
   CASE "case001": result$ = "001"
   CASE "case002": result$ = "002"
   CASE "case003": result$ = "003"
   CASE "case004": result$ = "004"
   CASE "case005": result$ = "005"
   CASE "case006": result$ = "006"
   CASE "case007": result$ = "007"
   CASE "case008": result$ = "008"
   CASE "case009": result$ = "009"
   CASE "case010": result$ = "010"
   CASE "case011": result$ = "011"
   CASE "case012": result$ = "012"
   CASE "case013": result$ = "013"
   CASE "case014": result$ = "014"
   CASE "case015": result$ = "015"
   CASE "case016": result$ = "016"
   CASE "case017": result$ = "017"
   CASE "case018": result$ = "018"
   CASE "case019": result$ = "019"
   CASE "case020": result$ = "020"
   CASE "case021": result$ = "021"
   CASE "case022": result$ = "022"
   CASE "case023": result$ = "023"
   CASE "case024": result$ = "024"
   CASE "case025": result$ = "025"
   CASE "case026": result$ = "026"
   CASE "case027": result$ = "027"
   CASE "case028": result$ = "028"
   CASE "case029": result$ = "029"
   CASE "case030": result$ = "030"
   CASE "case031": result$ = "031"
   CASE "case032": result$ = "032"
   CASE "case033": result$ = "033"
   CASE "case034": result$ = "034"
   CASE "case035": result$ = "035"
   CASE "case036": result$ = "036"
   CASE "case037": result$ = "037"
   CASE "case038": result$ = "038"
   CASE "case039": result$ = "039"
   CASE "case040": result$ = "040"
   CASE "case041": result$ = "041"
   CASE "case042": result$ = "042"
   CASE "case043": result$ = "043"
   CASE "case044": result$ = "044"
   CASE "case045": result$ = "045"
   CASE "case046": result$ = "046"
   CASE "case047": result$ = "047"
   CASE "case048": result$ = "048"
   CASE "case049": result$ = "049"
   CASE "case050": result$ = "050"
   CASE "case051": result$ = "051"
   CASE "case052": result$ = "052"
   CASE "case053": result$ = "053"
   CASE "case054": result$ = "054"
   CASE "case055": result$ = "055"
   CASE "case056": result$ = "056"
   CASE "case057": result$ = "057"
   CASE "case058": result$ = "058"
   CASE "case059": result$ = "059"
   CASE "case060": result$ = "060"
   CASE "case061": result$ = "061"
   CASE "case062": result$ = "062"
   CASE "case063": result$ = "063"
   CASE "case064": result$ = "064"
   CASE "case065": result$ = "065"
   CASE "case066": result$ = "066"
   CASE "case067": result$ = "067"
   CASE "case068": result$ = "068"
   CASE "case069": result$ = "069"
   CASE "case070": result$ = "070"
   CASE "case071": result$ = "071"
   CASE "case072": result$ = "072"
   CASE "case073": result$ = "073"
   CASE "case074": result$ = "074"
   CASE "case075": result$ = "075"
   CASE "case076": result$ = "076"
   CASE "case077": result$ = "077"
   CASE "case078": result$ = "078"
   CASE "case079": result$ = "079"
   CASE "case080": result$ = "080"
   CASE "case081": result$ = "081"
   CASE "case082": result$ = "082"
   CASE "case083": result$ = "083"
   CASE "case084": result$ = "084"
   CASE "case085": result$ = "085"
   CASE "case086": result$ = "086"
   CASE "case087": result$ = "087"
   CASE "case088": result$ = "088"
   CASE "case089": result$ = "089"
   CASE "case090": result$ = "090"
   CASE "case091": result$ = "091"
   CASE "case092": result$ = "092"
   CASE "case093": result$ = "093"
   CASE "case094": result$ = "094"
   CASE "case095": result$ = "095"
   CASE "case096": result$ = "096"
   CASE "case097": result$ = "097"
   CASE "case098": result$ = "098"
   CASE "case099": result$ = "099"
   CASE "case100": result$ = "100"
   CASE "case101": result$ = "101"
   CASE "case102": result$ = "102"
   CASE "case103": result$ = "103"
   CASE "case104": result$ = "104"
   CASE "case105": result$ = "105"
   CASE "case106": result$ = "106"
   CASE "case107": result$ = "107"
   CASE "case108": result$ = "108"
   CASE "case109": result$ = "109"
   CASE "case110": result$ = "110"
   CASE "case111": result$ = "111"
   CASE "case112": result$ = "112"
   CASE "case113": result$ = "113"
   CASE "case114": result$ = "114"
   CASE "case115": result$ = "115"
   CASE "case116": result$ = "116"
   CASE "case117": result$ = "117"
   CASE "case118": result$ = "118"
   CASE "case119": result$ = "119"
   CASE "case120": result$ = "120"
   CASE "case121": result$ = "121"
   CASE "case122": result$ = "122"
   CASE "case123": result$ = "123"
   CASE "case124": result$ = "124"
   CASE "case125": result$ = "125"
   CASE "case126": result$ = "126"
   CASE "case127": result$ = "127"
   CASE "case128": result$ = "128"
   CASE "case129": result$ = "129"
   CASE "case130": result$ = "130"
   CASE "case131": result$ = "131"
   CASE "case132": result$ = "132"
   CASE "case133": result$ = "133"
   CASE "case134": result$ = "134"
   CASE "case135": result$ = "135"
   CASE "case136": result$ = "136"
   CASE "case137": result$ = "137"
   CASE "case138": result$ = "138"
   CASE "case139": result$ = "139"
   CASE "case140": result$ = "140"
   CASE "case141": result$ = "141"
   CASE "case142": result$ = "142"
   CASE "case143": result$ = "143"
   CASE "case144": result$ = "144"
   CASE "case145": result$ = "145"
   CASE "case146": result$ = "146"
   CASE "case147": result$ = "147"
   CASE "case148": result$ = "148"
   CASE "case149": result$ = "149"
   CASE "case150": result$ = "150"
   CASE "case151": result$ = "151"
   CASE "case152": result$ = "152"
   CASE "case153": result$ = "153"
   CASE "case154": result$ = "154"
   CASE "case155": result$ = "155"
   CASE "case156": result$ = "156"
   CASE "case157": result$ = "157"
   CASE "case158": result$ = "158"
   CASE "case159": result$ = "159"
   CASE "case160": result$ = "160"
   CASE "case161": result$ = "161"
   CASE "case162": result$ = "162"
   CASE "case163": result$ = "163"
   CASE "case164": result$ = "164"
   CASE "case165": result$ = "165"
   CASE "case166": result$ = "166"
   CASE "case167": result$ = "167"
   CASE "case168": result$ = "168"
   CASE "case169": result$ = "169"
   CASE "case170": result$ = "170"
   CASE "case171": result$ = "171"
   CASE "case172": result$ = "172"
   CASE "case173": result$ = "173"
   CASE "case174": result$ = "174"
   CASE "case175": result$ = "175"
   CASE "case176": result$ = "176"
   CASE "case177": result$ = "177"
   CASE "case178": result$ = "178"
   CASE "case179": result$ = "179"
   CASE "case180": result$ = "180"
   CASE "case181": result$ = "181"
   CASE "case182": result$ = "182"
   CASE "case183": result$ = "183"
   CASE "case184": result$ = "184"
   CASE "case185": result$ = "185"
   CASE "case186": result$ = "186"
   CASE "case187": result$ = "187"
   CASE "case188": result$ = "188"
   CASE "case189": result$ = "189"
   CASE "case190": result$ = "190"
   CASE "case191": result$ = "191"
   CASE "case192": result$ = "192"
   CASE "case193": result$ = "193"
   CASE "case194": result$ = "194"
   CASE "case195": result$ = "195"
   CASE "case196": result$ = "196"
   CASE "case197": result$ = "197"
   CASE "case198": result$ = "198"
   CASE "case199": result$ = "199"
   CASE "case200": result$ = "200"
   CASE ELSE: result$ = "ELSE"
 END SELECT
 
 IF result$ = "ELSE" THEN
   pass% = 2
 ELSEIF result$ <> "" THEN
   pass% = 1
 ENDIF
END SUB

SUB SelectTestInt(val%)
 LOCAL result%
 result% = -1
 
 SELECT CASE val%
   CASE 1: result% = 1
   CASE 2: result% = 2
   CASE 3: result% = 3
   CASE 4: result% = 4
   CASE 5: result% = 5
   CASE 6: result% = 6
   CASE 7: result% = 7
   CASE 8: result% = 8
   CASE 9: result% = 9
   CASE 10: result% = 10
   CASE 11: result% = 11
   CASE 12: result% = 12
   CASE 13: result% = 13
   CASE 14: result% = 14
   CASE 15: result% = 15
   CASE 16: result% = 16
   CASE 17: result% = 17
   CASE 18: result% = 18
   CASE 19: result% = 19
   CASE 20: result% = 20
   CASE 21: result% = 21
   CASE 22: result% = 22
   CASE 23: result% = 23
   CASE 24: result% = 24
   CASE 25: result% = 25
   CASE 26: result% = 26
   CASE 27: result% = 27
   CASE 28: result% = 28
   CASE 29: result% = 29
   CASE 30: result% = 30
   CASE 31: result% = 31
   CASE 32: result% = 32
   CASE 33: result% = 33
   CASE 34: result% = 34
   CASE 35: result% = 35
   CASE 36: result% = 36
   CASE 37: result% = 37
   CASE 38: result% = 38
   CASE 39: result% = 39
   CASE 40: result% = 40
   CASE 41: result% = 41
   CASE 42: result% = 42
   CASE 43: result% = 43
   CASE 44: result% = 44
   CASE 45: result% = 45
   CASE 46: result% = 46
   CASE 47: result% = 47
   CASE 48: result% = 48
   CASE 49: result% = 49
   CASE 50: result% = 50
   CASE 51: result% = 51
   CASE 52: result% = 52
   CASE 53: result% = 53
   CASE 54: result% = 54
   CASE 55: result% = 55
   CASE 56: result% = 56
   CASE 57: result% = 57
   CASE 58: result% = 58
   CASE 59: result% = 59
   CASE 60: result% = 60
   CASE 61: result% = 61
   CASE 62: result% = 62
   CASE 63: result% = 63
   CASE 64: result% = 64
   CASE 65: result% = 65
   CASE 66: result% = 66
   CASE 67: result% = 67
   CASE 68: result% = 68
   CASE 69: result% = 69
   CASE 70: result% = 70
   CASE 71: result% = 71
   CASE 72: result% = 72
   CASE 73: result% = 73
   CASE 74: result% = 74
   CASE 75: result% = 75
   CASE 76: result% = 76
   CASE 77: result% = 77
   CASE 78: result% = 78
   CASE 79: result% = 79
   CASE 80: result% = 80
   CASE 81: result% = 81
   CASE 82: result% = 82
   CASE 83: result% = 83
   CASE 84: result% = 84
   CASE 85: result% = 85
   CASE 86: result% = 86
   CASE 87: result% = 87
   CASE 88: result% = 88
   CASE 89: result% = 89
   CASE 90: result% = 90
   CASE 91: result% = 91
   CASE 92: result% = 92
   CASE 93: result% = 93
   CASE 94: result% = 94
   CASE 95: result% = 95
   CASE 96: result% = 96
   CASE 97: result% = 97
   CASE 98: result% = 98
   CASE 99: result% = 99
   CASE 100: result% = 100
   CASE 101: result% = 101
   CASE 102: result% = 102
   CASE 103: result% = 103
   CASE 104: result% = 104
   CASE 105: result% = 105
   CASE 106: result% = 106
   CASE 107: result% = 107
   CASE 108: result% = 108
   CASE 109: result% = 109
   CASE 110: result% = 110
   CASE 111: result% = 111
   CASE 112: result% = 112
   CASE 113: result% = 113
   CASE 114: result% = 114
   CASE 115: result% = 115
   CASE 116: result% = 116
   CASE 117: result% = 117
   CASE 118: result% = 118
   CASE 119: result% = 119
   CASE 120: result% = 120
   CASE 121: result% = 121
   CASE 122: result% = 122
   CASE 123: result% = 123
   CASE 124: result% = 124
   CASE 125: result% = 125
   CASE 126: result% = 126
   CASE 127: result% = 127
   CASE 128: result% = 128
   CASE 129: result% = 129
   CASE 130: result% = 130
   CASE 131: result% = 131
   CASE 132: result% = 132
   CASE 133: result% = 133
   CASE 134: result% = 134
   CASE 135: result% = 135
   CASE 136: result% = 136
   CASE 137: result% = 137
   CASE 138: result% = 138
   CASE 139: result% = 139
   CASE 140: result% = 140
   CASE 141: result% = 141
   CASE 142: result% = 142
   CASE 143: result% = 143
   CASE 144: result% = 144
   CASE 145: result% = 145
   CASE 146: result% = 146
   CASE 147: result% = 147
   CASE 148: result% = 148
   CASE 149: result% = 149
   CASE 150: result% = 150
   CASE 151: result% = 151
   CASE 152: result% = 152
   CASE 153: result% = 153
   CASE 154: result% = 154
   CASE 155: result% = 155
   CASE 156: result% = 156
   CASE 157: result% = 157
   CASE 158: result% = 158
   CASE 159: result% = 159
   CASE 160: result% = 160
   CASE 161: result% = 161
   CASE 162: result% = 162
   CASE 163: result% = 163
   CASE 164: result% = 164
   CASE 165: result% = 165
   CASE 166: result% = 166
   CASE 167: result% = 167
   CASE 168: result% = 168
   CASE 169: result% = 169
   CASE 170: result% = 170
   CASE 171: result% = 171
   CASE 172: result% = 172
   CASE 173: result% = 173
   CASE 174: result% = 174
   CASE 175: result% = 175
   CASE 176: result% = 176
   CASE 177: result% = 177
   CASE 178: result% = 178
   CASE 179: result% = 179
   CASE 180: result% = 180
   CASE 181: result% = 181
   CASE 182: result% = 182
   CASE 183: result% = 183
   CASE 184: result% = 184
   CASE 185: result% = 185
   CASE 186: result% = 186
   CASE 187: result% = 187
   CASE 188: result% = 188
   CASE 189: result% = 189
   CASE 190: result% = 190
   CASE 191: result% = 191
   CASE 192: result% = 192
   CASE 193: result% = 193
   CASE 194: result% = 194
   CASE 195: result% = 195
   CASE 196: result% = 196
   CASE 197: result% = 197
   CASE 198: result% = 198
   CASE 199: result% = 199
   CASE 200: result% = 200
   CASE ELSE: result% = 0
 END SELECT
 
 IF result% = val% THEN pass% = 1
END SUB
 
Posted: 01:08pm
13 Jan 2026
Copy link to clipboard
bfwolf
Senior Member

I've been experimenting again with Lizby's database experiments...

I don't know if the following should work, or if it's "too complicated" for the 'EXECUTE' command?

Option Base 1
Option Explicit
Option Escape

'Next line throws error if enabled: "Error: Invalid member definition in TYPE"
'Type TPers phone As integer surname As string Length 8 name As string Length 7 pad As string Length 2 End Type

Dim TypeNam1$ As String = "TPerson\n\r"
Dim TypeDef1$ As String = "Type "
TypeDef1$ = TypeDef1$ + TypeNam1$
TypeDef1$ = TypeDef1$ + "phone As integer\n\r"
TypeDef1$ = TypeDef1$ + "surname As string Length 8\n\r"
TypeDef1$ = TypeDef1$ + "name As string Length 7\n\r"
TypeDef1$ = TypeDef1$ + "padding As string Length 2\n\r"
TypeDef1$ = TypeDef1$ + "End Type\n\r"

Dim TypeDim1$ As String
TypeDim1$ = "Dim people(2) As " + TypeNam1$

Print TypeDef1$
Print TypeDim1$

'Next line throws error: "Error : No matching END TYPE"
Execute TypeDef1$

Execute TypeDim1$

Print Struct(Type, "TPerson")
End


I also don't know if the type definition commented out in the example above should work as a one-liner?:
Type TPers phone As integer surname As string Length 8 name As string Length 7 pad As string Length 2 End Type


Perhaps one could use ',' as a separator for the one-liner type, even if the syntax then differs from Microsoft's QBasic?
Type TPers, phone As integer, surname As string, Length 8, name As string Length 7, pad As string Length 2, End Type


But if it did work, it would be fantastic for Lizby's database experiments!
https://www.thebackshed.com/forum/ViewTopic.php?FID=16&TID=18546

Another way to make the database more "generic" would be a "database generator program" that uses a menu to determine the fields of the table(s) and then outputs a finished BASIC program to a file.

Regards.
 
Posted: 01:18pm
13 Jan 2026
Copy link to clipboard
matherp
Guru

Types are defined before the program is run in the same way as subroutines. This can't possibly work any more than trying to define a subroutine using execute could.
 
Posted: 01:30pm
13 Jan 2026
Copy link to clipboard
bfwolf
Senior Member

  matherp said  Types are defined before the program is run in the same way as subroutines. This can't possibly work any more than trying to define a subroutine using execute could.


Ah, OK, that's what I suspected – nothing can be done about it then.

Another possibility would be to have the type definitions in an #include file. But that would only work with 'CMM2 LOAD'.

Then one have to use the "program generator" method for a generic database-system.
 
Posted: 04:20pm
13 Jan 2026
Copy link to clipboard
JanVolk
Guru

Error: Invalid address - resetting

This happened after a few minutes with the part of the program that previously worked fine. In the past, I had to adjust the I2C speed on an RP2040: OPTION SYSTEM I2C GP4, GP5, SLOW.
With the RP2350, I now see that the screen is completely scrambled when using SLOW with this part of the program. Perhaps something changed with FAST and SLOW? I changed the Byte in the LCD I2C subs to AByte.
But then I also get "Error: Invalid address - resetting" with V6.02.00RC4. The program stops. If I change it back to OPTION SYSTEM I2C GP4, GP5, the LCD screen displays normally until the message "Error: Invalid address - resetting" with TeraTerm is displayed, and the program stops.
With the RP2040 running V6.01.00 and OPTION SYSTEM I2C GP4, GP5, there was no problem with the LCD screen and no "Error: Invalid address - resetting" error. With OPTION SYSTEM I2C GP4, GP5, and SLOW, the LCD screen was mixed. The program continued to run. (Previously, this was without SLOW.)
With the RP2040 running V6.02.00RC4 and OPTION SYSTEM I2C GP4, GP5, there was no problem with the LCD screen and no "Error: Invalid address - resetting" error. With OPTION SYSTEM I2C GP4, GP5, and SLOW, the LCD screen was mixed. The program continued to run. (Previously, this was without SLOW.)
Later, I tested with Byte on an RP2040 and RP2350A V6.02.00RC4 and still no problems, so the "Error: Invalid address - resetting" error is not the problem, but with the RP2350, this message appeared after a few minutes. Also the OPTION RTC AUTO ENABLE is sometimes removed but I can't recreate it anymore?
If you change the bus speed for I2C to SLOW (100kHz manual), the LCD output is no longer correct.
So, apparently something has changed in the FAST (Standard 400kHz manual) and SLOW (100kHz manual) settings for OPTION SYSTEM I2C?
The "Error: Invalid address - resetting" only occurs with the RP2350 series.
When I switch from V6.01.00 to V6.02.00 with an RP2040, I can no longer write to or read from A:. "Error: Error during device operation," so A: must first be formatted (DRIVE "A:/FORMAT").

> option list
PicoMite MMBasic RP2350A V6.02.00RC4
OPTION SYSTEM SPI GP10,GP11,GP12
OPTION SYSTEM I2C GP4,GP5
OPTION FLASH SIZE 16777216
OPTION COLOURCODE ON
OPTION HEARTBEAT OFF
OPTION PICO OFF
OPTION CPUSPEED (KHz) 200000
OPTION DISPLAY 50, 100
OPTION SDCARD GP15
OPTION RTC AUTO ENABLE
OPTION F1 FLASH RUN 1

'*** DEMOKAS ***
Const Buiten_temp = 5.6
Const binnen_temp = 19.2
Const Raamstand_m = 2.0

'*** Hier de speciale tekens ***
LCDI2C_Init &H20, 1, 0, 2, 3   'I2CAddr: &H20=20x4 LCDI2C, &H38=16x2 LCDI2C
LCDI2C_CLEAR
LCDI2C_BackLightOn
LCDI2C_CMD(64)                 'Chr$(0)
LCDI2C_DATA(7): LCDI2C_DATA(5): LCDI2C_DATA(7): LCDI2C_DATA(0)'Gradenteken B1-4
LCDI2C_DATA(0): LCDI2C_DATA(0): LCDI2C_DATA(0): LCDI2C_DATA(0)'Gradenteken B5-8
LCDI2C_CMD(80)                 'Chr$(2)
LCDI2C_DATA(0): LCDI2C_DATA(0): LCDI2C_DATA(0): LCDI2C_DATA(0)'LEEG teken B1-4
LCDI2C_DATA(0): LCDI2C_DATA(0): LCDI2C_DATA(0): LCDI2C_DATA(0)'LEEG teken B5-8

Do
 Beeld                        'Bouw met een I2C LCD2004 display het menu op.
 Pause 500
Loop

'*** Bouw het menu beeld op aan het begin van het programma. ***"
Sub Beeld
 LCDI2C 1, 1, "BuitenTemp.:       C"
 LCDI2C 1,15, Str$(Buiten_temp, 2, 1)
 LCDI2C 1,19, Chr$(0)
 LCDI2C 2, 1, "BinnenTemp.:       C"
 LCDI2C 2,15, Str$(Binnen_temp, 2, 1)
 LCDI2C 2,19, Chr$(0)
 LCDI2C 3, 1, "Raamstand  :       %"
 LCDI2C 3,15, Str$(Raamstand_m, 2, 1)
 LCDI2C 4, 1, "di"
 LCDI2C 4, 4, Left$(Date$, 10)
 LCDI2C 4,15, Left$(Time$, 5)
End Sub

'*** LCDI2C subroutines. ****
Sub LCDI2C(LineNum, CharPos, Text$)
 Local I
 If LineNum = 1 Then I = (&H80 + CharPos - 1)
 If LineNum = 2 Then I = (&HC0 + CharPos - 1)
 If LineNum = 3 Then I = (&H94 + CharPos - 1)
 If LineNum = 4 Then I = (&HD4 + CharPos - 1)
 LCDI2C_CMD(I)
 For I = 1 To Len(Text$)
   LCDI2C_DATA(Asc(Mid$(Text$, I, 1)))
 Next I
End Sub
'
Sub LCDI2C_Clear()
 LCDI2C_CMD(&H01)
 Pause 3
End Sub
'
Sub LCDI2C_Init I2CAddr, NibPos, RSBitNo, ENBitNo, BLBitNo
 Dim LCDI2C_BackLight
 LCDI2C_BackLight = 2 ^ BLBitNo
 Dim LCDI2C_LCDBackLight
 LCDI2C_LCDBackLight = LCDI2C_BackLight
 Dim LCDI2C_I2CAddr
 LCDI2C_I2CAddr = I2CAddr
 Dim LCDI2C_RSDataMask
 LCDI2C_RSDataMask = 2 ^ RSBitNo
 Dim LCDI2C_EMask
 LCDI2C_EMask = 2 ^ ENBitNo
 Dim LCDI2C_NibPos
 LCDI2C_NibPos = NiBPos
 LCDI2C_CMD(&H33)
 LCDI2C_CMD(&H32)
 LCDI2C_CMD(&H28)
 LCDI2C_CMD(&H0C)
 LCDI2C_CMD(&H06)
 LCDI2C_CMD(&H01)
 LCDI2C_BackLightOff()
End Sub
'
Sub LCDI2C_Close()
 I2C CLOSE
End Sub
'
Sub LCDI2C_BacklightOn
 LCDI2C_LCDBackLight = LCDI2C_Backlight
 LCDI2C_WireWrite(0)
End Sub
'
Sub LCDI2C_BacklightOff
 LCDI2C_LCDBackLight = &H00
 LCDI2C_WireWrite(0)
End Sub
'
Sub LCDI2C_CMD(AByte)
 LCDI2C_DirectSend(AByte And &HF0)
 LCDI2C_DirectSend((AByte And &H0F) * 16)
End Sub
'
Sub LCDI2C_DATA(AByte)
 LCDI2C_DirectSend((AByte And &HF0) Or LCDI2C_RSDataMask)
 LCDI2C_DirectSend(((AByte And &H0F) * 16) Or LCDI2C_RSDataMask)
End Sub
'
Sub LCDI2C_DirectSend(AByte)
 Local B, B1
 If LCDI2C_NibPos = 0 Then
   B1 = AByte \ 16
 Else
   B1 = AByte
 EndIf
 B = B1 Or LCDI2C_EMask Or LCDI2C_LCDBackLight
 I2C WRITE LCDI2C_I2CAddr, 0, 1, B
 I2C WRITE LCDI2C_I2CAddr, 0, 1, B1 Or LCDI2C_LCDBackLight
End Sub
'
Sub LCDI2C_WireWrite(AByte)
 I2C WRITE LCDI2C_I2CAddr, 0, 1, AByte Or LCDI2C_LCDBackLight
End Sub


Kind regards,

Jan.
 
Posted: 04:47pm
13 Jan 2026
Copy link to clipboard
matherp
Guru

I don't have one of these display so difficult to replicate. Please disable RTC AUTO and see if the problem still occurs
 
Posted: 05:48pm
13 Jan 2026
Copy link to clipboard
JanVolk
Guru

Could it be the latest addition of the new RTC module?

If you install the PicoMite MMBasic RP2350A V6.02.00RC4 firmware, use the option list, and no pins are connected, and load the DEMOKAS.bas program, it will also happen after 4 minutes when Windows notifies you with the message "Error: Invalid address - resetting."

When I remove the Raspberry Pi Pico module from its holder, the RTC AUTO ENABLE option is removed from the list.
When I then run the test, the program stops after about 4 minutes.
If I replace the module without the RTC AUTO ENABLE option in the list and start the program, it continues to work, but for much longer, and then stops after 12 minutes. I can easily follow this because the RTC time on the LCD screen starts at 00:00.


Kind regards,

Jan.
Edited 2026-01-14 04:13 by JanVolk
 
Posted: 06:54pm
13 Jan 2026
Copy link to clipboard
matherp
Guru

No.

I've even set the RTC background update rate to 60 seconds and it has run for 30mins with no issue (no display connected)
 
Posted: 07:35pm
13 Jan 2026
Copy link to clipboard
JanVolk
Guru

Okay. Then I'll do some more research with flash_nuke and another RP2350 module and another DS3231. Thanks in advance.
 
Posted: 07:38pm
13 Jan 2026
Copy link to clipboard
lizby
Guru

  bfwolf said  I've been experimenting


This with colons alone at the command prompt does not fail for me:
Type: TPers phone As integer: surname As string Length 8: name As string Length 7: pad As string Length 2: End Type


(Don't know about any of the other issues--but I don't see how to generalize a database manager from a structure)
 
Posted: 08:09pm
13 Jan 2026
Copy link to clipboard
bfwolf
Senior Member

  lizby said  
This with colons alone at the command prompt does not fail for me:
Type: TPers phone As integer: surname As string Length 8: name As string Length 7: pad As string Length 2: End Type


Ah - good to know and a great tip!

I also briefly considered whether ':' could work as a separator, but I didn't try it because I thought ':' separates statements and the entire "block" 'Type typeName memberDefinition ... End Type' would count as one statement.

I tried the "one-liner" because I thought it might simplify 'EXECUTE'.

  lizby said  (Don't know about any of the other issues--but I don't see how to generalize a database manager from a structure)


You could write a "database editor" in BASIC where you can enter tables using their fields (field names and types) and design forms. You could also design reports. This could even be done with a GUI. The information could then be saved as a "project file," for example, as a JSON or XML file.

From this "project," you could then generate the MMBasic code using an "export function." This code would contain the struct types, the table DIMs, and the corresponding SUBs.

The whole thing could then be combined with an existing "framework application" (by copying the files together) to create a complete BASIC database program.

Regards, bfwolf
 
Posted: 10:40pm
13 Jan 2026
Copy link to clipboard
matherp
Guru

Setting up types at the comand prompt is fine but they are overwritten when you run a program
 
Posted: 11:23pm
13 Jan 2026
Copy link to clipboard
bfwolf
Senior Member

  matherp said  Setting up types at the comand prompt is fine but they are overwritten when you run a program


Hi @Peter: If that was referring to my previous post, you probably misunderstood me.

I understand that you can define types as "one-liners" in the command line — for example, for testing — but that they are deleted with 'RUN' because RUN deletes all variables, and therefore presumably also types.

My idea is to write a program ("database generator") that exports an MMBasic program with appropriate types, forms, etc., to the file system based on user-defined table structures. From there, it can be loaded and run.

The exported program could then potentially even be started directly from the database generator using 'CHAIN' (or 'RUN'?).
 
Posted: 12:55am
14 Jan 2026
Copy link to clipboard
phil99
Guru


  Quote  The exported program could then potentially even be started directly from the database generator using 'CHAIN' (or 'RUN'?).

Yes that should work.
Have done a similar thing using RUN.
The program starts in "Learning Mode" by copying itself to A: then goes through the learning process, appending the new data to the disc copy. It then RUNs the disc copy which detects the new data and switches to "Operating Mode".
 
   Page 7 of 9    
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2026