The swiss_micros packages
Table of Contents
I wrote these two packages so I would only have to parse the console once. dm_set_time already uses them; dm_receive and dm_send will. If you only wanted to set the clock, the section index is enough.
Two packages, one rule #
I keep calculator-facing literals in Swiss_Micros.Console_IO. I keep flags in the GetOpt hierarchy that starts at
Swiss_Micros.Command_Line.
Serial console (Swiss_Micros.Console_IO) #
The calculator presents a line-oriented console at 38400 8N1, no flow control. It emit the prompt twice on purpose
so a it’s easier for a line-based reader to parse. AdaCL.Serial_IO.Expect can do both: Line and character based
prompts.
VOYAGER >>
VOYAGER >>
UART parameters and the console verbs live in Swiss_Micros.Console_IO:
| Constant | Console text | Meaning |
|---|---|---|
Help |
? |
List console commands |
Key_Press |
p |
Inject a key |
Dump_Memory |
s |
Save memory toward the host (dm_receive) |
Load_Memory |
l |
Load memory from the host (dm_send) |
Console_Timeout |
ct |
Console idle timeout (minutes) |
Invoke_Bootloader |
bootloader |
Enter the firmware bootloader |
Get_Time |
t |
Read the clock. Reply: 2026-09-22 18:09:26 TUE |
Set_Time |
ts |
Set an absolute clock. Argument: compact YYYYMMDD HHMMSS |
Update_Time |
td |
Shift the clock by a minute offset (DST). Not a timestamp |
Toggle_Keyboard_Output |
kb |
Keyboard trace |
Toggle_Display_Output |
d |
Display trace |
Read_Battery_Voltage |
b |
Battery voltage |
Get_Time and Set_Time do not share a format. I learned that the hard way. t prints %Y-%m-%d %H:%M:%S %a with
the weekday upper-cased. ts accepts only the fifteen-character compact stamp. td is a minute delta, not a third
layout.
Date_Time_Image builds only the ts stamp. Pass Use_UTC => True when I want GMT instead of the local offset.
I open the port with USB_Serial_Speed, Bits, Stop_Bits, Parity, and Flow. I wait for Prompt, write a verb
plus arguments, wait for the prompt again. That is the whole protocol. dm_set_time also drops ct 1 first so the
console does not sit open after the programme leaves.
Command line (Swiss_Micros.Command_Line) #
AdaCL.Command_Line.GetOpt is object-oriented, re-entrant, and hierarchical. The second property is the one
that pays off here: common options live on a shared tagged type; each tool extends that type instead of copy-and-pasting
flags.
AdaCL.Command_Line.GetOpt.Object
↑
Swiss_Micros.Command_Line.Object -- -d / --device / DM_SERIAL_DEVICE
↑
<tool-specific Object> -- e.g. -u / --utc on dm_set_time
Swiss_Micros.Command_Line.Object already:
- accepts
-d/--device; - seeds
DevicefromDM_SERIAL_DEVICEif the flag is absent; - raises
Option_Missing_Errorwhen neither source supplies a device; - prints the device help block, then calls the inherited
Write_Help.
A new tool therefore:
- derives its options type from
Swiss_Micros.Command_Line.Object; - extends
Patternwith any extra short flags (dm_set_timeappendsUTC_Short); - overrides
Analyze_GNU/Analyze_Without_Argument/Analyze_Fileonly for new tokens, callingSuperin the finalelse; - calls
Super.ParseandSuper.Write_Helpat the end of its own; - opens the port on
This.Deviceat theConsole_IOsettings; - speaks the verbs in
Console_IO.
I do not copy the device parser. I extend it.
Writing your own tool #
dm_set_time is the working specimen. The child type adds -u / --utc and one operand. Analyze_File is the operand
hook — not a file name. It demands length 15 and a Spitbol match: eight decimal digits, a space, six decimal digits.
Time returns that operand when it is set; otherwise it calls Date_Time_Image. --utc is ignored once a stamp is
present.
The main programme then:
- wakes the console with a blank line;
- sends
ct 1and waits for the confirmation line plusPrompt; - sends
tsand the compact stamp; - sends
tand prints whatever came back — that line is the hyphenated form, not the stamp just written.
Sketch of the GetOpt override:
type Object is new Swiss_Micros.Command_Line.Object with record
Use_UTC : Boolean := False;
end record;
overriding procedure Analyze_GNU (This : in out Object) is
Super : Swiss_Micros.Command_Line.Object renames
Swiss_Micros.Command_Line.Object (This);
begin
if This.Get_GNU_Option = "utc" then
This.Use_UTC := True;
else
Super.Analyze_GNU;
end if;
end Analyze_GNU;
Worked example: The dm_set_time packages.