v4_cli 0.5.0

CLI tool for V4 VM bytecode deployment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# V4 SYS Instruction Opcodes

## Overview

The `SYS` instruction (opcode `0x60`) provides a gateway to Hardware Abstraction Layer (HAL) functions. It allows V4 bytecode to interact with GPIO, UART, and timers without platform-specific knowledge.

**Format**: `SYS <id:u8>`

Where `id` specifies which HAL function to call.

## SYS ID Assignment

### GPIO Operations (0x00 - 0x0F)

| ID   | Function | Stack Effect | Description |
|------|----------|--------------|-------------|
| 0x00 | `GPIO_INIT` | `(pin mode -- err)` | Initialize GPIO pin |
| 0x01 | `GPIO_WRITE` | `(pin value -- err)` | Write to GPIO pin |
| 0x02 | `GPIO_READ` | `(pin -- value err)` | Read from GPIO pin |

#### GPIO_INIT (0x00)

**Stack**: `(pin mode -- err)`

**Description**: Initialize a GPIO pin with specified mode.

**Parameters**:
- `pin`: GPIO pin number (platform-specific)
- `mode`: Pin mode (0=INPUT, 1=OUTPUT, 2=INPUT_PULLUP, 3=INPUT_PULLDOWN)

**Returns**:
- `err`: Error code (0 = success)

**Example**:
```forth
\ Configure pin 13 as output
13 1 SYS 0x00
```

---

#### GPIO_WRITE (0x01)

**Stack**: `(pin value -- err)`

**Description**: Write a digital value to GPIO pin.

**Parameters**:
- `pin`: GPIO pin number
- `value`: 0 for LOW, non-zero for HIGH

**Returns**:
- `err`: Error code (0 = success)

**Example**:
```forth
\ Set pin 13 high
13 1 SYS 0x01

\ Set pin 13 low
13 0 SYS 0x01
```

---

#### GPIO_READ (0x02)

**Stack**: `(pin -- value err)`

**Description**: Read the current state of GPIO pin.

**Parameters**:
- `pin`: GPIO pin number

**Returns**:
- `value`: Pin state (0 or 1)
- `err`: Error code (0 = success)

**Example**:
```forth
\ Read pin 5
5 SYS 0x02
\ Stack now has: value err
```

---

### UART Operations (0x10 - 0x1F)

| ID   | Function | Stack Effect | Description |
|------|----------|--------------|-------------|
| 0x10 | `UART_INIT` | `(port baudrate -- err)` | Initialize UART port |
| 0x11 | `UART_PUTC` | `(port char -- err)` | Send one character |
| 0x12 | `UART_GETC` | `(port -- char err)` | Receive one character |

#### UART_INIT (0x10)

**Stack**: `(port baudrate -- err)`

**Description**: Initialize UART port with specified baud rate.

**Parameters**:
- `port`: UART port number (typically 0-3)
- `baudrate`: Baud rate (e.g., 9600, 115200)

**Returns**:
- `err`: Error code (0 = success)

**Example**:
```forth
\ Initialize UART0 at 115200 baud
0 115200 SYS 0x10
```

---

#### UART_PUTC (0x11)

**Stack**: `(port char -- err)`

**Description**: Send a single character via UART.

**Parameters**:
- `port`: UART port number
- `char`: Character to send (ASCII value)

**Returns**:
- `err`: Error code (0 = success)

**Example**:
```forth
\ Send 'A' (ASCII 65) to UART0
0 65 SYS 0x11
```

---

#### UART_GETC (0x12)

**Stack**: `(port -- char err)`

**Description**: Receive a single character from UART (non-blocking).

**Parameters**:
- `port`: UART port number

**Returns**:
- `char`: Received character (ASCII value), or undefined if error
- `err`: Error code (0 = success, negative = no data or error)

**Example**:
```forth
\ Try to receive from UART0
0 SYS 0x12
\ Stack: char err
\ Check if err is 0 before using char
```

---

### Timer Operations (0x20 - 0x2F)

| ID   | Function | Stack Effect | Description |
|------|----------|--------------|-------------|
| 0x20 | `MILLIS` | `( -- ms)` | Get milliseconds since startup |
| 0x21 | `MICROS` | `( -- us_lo us_hi)` | Get microseconds (64-bit) |
| 0x22 | `DELAY_MS` | `(ms -- )` | Delay milliseconds |
| 0x23 | `DELAY_US` | `(us -- )` | Delay microseconds |

#### MILLIS (0x20)

**Stack**: `( -- ms)`

**Description**: Get milliseconds since system startup.

**Returns**:
- `ms`: Milliseconds (32-bit, wraps after ~49 days)

**Example**:
```forth
\ Get current time
SYS 0x20
\ Stack: ms
```

---

#### MICROS (0x21)

**Stack**: `( -- us_lo us_hi)`

**Description**: Get microseconds since system startup (64-bit).

**Returns**:
- `us_lo`: Lower 32 bits of microseconds
- `us_hi`: Upper 32 bits of microseconds

**Example**:
```forth
\ Get current time in microseconds
SYS 0x21
\ Stack: us_lo us_hi
```

---

#### DELAY_MS (0x22)

**Stack**: `(ms -- )`

**Description**: Blocking delay in milliseconds.

**Parameters**:
- `ms`: Milliseconds to delay

**Example**:
```forth
\ Delay 1000ms (1 second)
1000 SYS 0x22
```

---

#### DELAY_US (0x23)

**Stack**: `(us -- )`

**Description**: Blocking delay in microseconds.

**Parameters**:
- `us`: Microseconds to delay

**Example**:
```forth
\ Delay 100 microseconds
100 SYS 0x23
```

---

### System Operations (0xF0 - 0xFF)

| ID   | Function | Stack Effect | Description |
|------|----------|--------------|-------------|
| 0xFE | `SYSTEM_RESET` | `( -- )` | Reset microcontroller |
| 0xFF | `SYSTEM_INFO` | `( -- addr len)` | Get system info string |

#### SYSTEM_RESET (0xFE)

**Stack**: `( -- )`

**Description**: Perform a system reset (may not return).

**Example**:
```forth
\ Reset the system
SYS 0xFE
```

---

#### SYSTEM_INFO (0xFF)

**Stack**: `( -- addr len)`

**Description**: Get platform identification string.

**Returns**:
- `addr`: Address of string in memory
- `len`: Length of string

**Example**:
```forth
\ Get system info
SYS 0xFF
\ Stack: addr len
\ Can be used with UART to print platform name
```

---

## Usage Examples

### Blink LED Example

```forth
: SETUP
  13 1 SYS 0x00  \ Configure pin 13 as output
  DROP           \ Drop error code
;

: BLINK
  13 1 SYS 0x01  \ Set pin high
  DROP
  500 SYS 0x22   \ Delay 500ms
  13 0 SYS 0x01  \ Set pin low
  DROP
  500 SYS 0x22   \ Delay 500ms
;

: MAIN
  SETUP
  BEGIN BLINK AGAIN
;
```

### UART Echo Example

```forth
: UART-SETUP
  0 115200 SYS 0x10  \ Init UART0 at 115200
  DROP
;

: ECHO-ONCE
  0 SYS 0x12         \ Receive character
  DUP 0 EQ IF        \ Check if no error
    SWAP             \ Get char
    0 SWAP SYS 0x11  \ Send it back
    DROP             \ Drop error
  ELSE
    DROP DROP        \ Drop char and error
  THEN
;

: MAIN
  UART-SETUP
  BEGIN ECHO-ONCE 10 SYS 0x22 AGAIN  \ Loop with 10ms delay
;
```

### Button Input Example

```forth
: SETUP
  2 2 SYS 0x00   \ Configure pin 2 as input with pullup
  DROP
  13 1 SYS 0x00  \ Configure pin 13 as output
  DROP
;

: READ-BUTTON
  2 SYS 0x02     \ Read pin 2
  SWAP DROP      \ Keep value, drop error
;

: UPDATE-LED
  READ-BUTTON
  0 EQ IF        \ If button pressed (active low)
    13 1 SYS 0x01  \ Turn LED on
  ELSE
    13 0 SYS 0x01  \ Turn LED off
  THEN
  DROP           \ Drop error
;

: MAIN
  SETUP
  BEGIN UPDATE-LED 50 SYS 0x22 AGAIN
;
```

---

## Error Handling

All SYS operations that can fail leave an error code on the stack:

- `0`: Success
- Negative: Error (see `errors.def`)

**Best Practice**: Always check error codes in production code.

```forth
: SAFE-GPIO-WRITE
  13 1 SYS 0x01  \ Try to write
  DUP 0 NE IF    \ Check if error
    \ Handle error (e.g., print message)
    DROP
  ELSE
    DROP
  THEN
;
```

---

## Implementation Notes

### For V4-core Developers

The SYS instruction dispatcher in `src/core.cpp`:

```cpp
case v4::Op::SYS:
{
  uint8_t sys_id = code[ip++];

  switch (sys_id) {
    case 0x00:  // GPIO_INIT
      // Pop mode, pin
      // Call v4_hal_gpio_init
      // Push error
      break;
    // ... other cases
  }
  break;
}
```

### Platform Compatibility

SYS IDs are **platform-independent**. HAL implementations must provide consistent behavior across platforms.

---

## Future Extensions

Reserved ID ranges for future use:

- `0x30-0x3F`: I2C operations
- `0x40-0x4F`: SPI operations
- `0x50-0x5F`: PWM operations
- `0x60-0x6F`: ADC operations
- `0x70-0x7F`: DAC operations
- `0x80-0xEF`: User-defined extensions

---

## References

- [HAL API Specification]hal-api.md
- [V4 Opcode Reference]../include/v4/opcodes.def
- [Error Codes]../include/v4/errors.def