Crates.io | p101_sys |
lib.rs | p101_sys |
version | |
source | src |
created_at | 2024-10-09 21:36:15.220084 |
updated_at | 2024-10-09 21:36:15.220084 |
description | A library to build modular emulator of Olivetti Programma 101 |
homepage | |
repository | https://gitlab.com/cokkaai/programma_101/-/tree/master/sys |
max_upload_size | |
id | 1403073 |
Cargo.toml error: | TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
This crate provides the building blocks of the emulator. Such blocks are indipendent components that communicates via a system bus emitting and consuming events. Each component is completely isolated and only knows about the system bus.
This loosely coupled architecture brings a lot of flexibility:
The event bus is implemented by System. Components register with the system, which keeps track of interested events in order to route messages. System is responsible to start all components, communicate events and coordinate shutdown.
Events, or messages, can be roughly grouped in two kinds.
This message instructs the receiving component to stop. All components must properly handle halt. The event is emitted by any component that wants to stop the emulator; the system broadcasts the halt event to all components and waits all to stop before shutting down.
This is the only message that is explicitly broadcasted and do not require the component to register for it.
All components must properly handle the halt message, completing or aborting any running tasks then shutting down. A component that does not stops prevents the system to shutdown.
New system status.
Comunicates the new value set on the precision wheel.
Status of the record program switch.
Status of the print program switch.
These messages instruct the consuming device to output the string payload.
The message notifies the storage that a card has been inserted and it is available for read/write operations.
The message notifies the storage that a card has been removed from the reader.
This message instructs the storage to read data from the card.
This message is emitted by storage devices when data has been read from the card.
The message instructs the storage component to write memory to the card inserted in the reader. The event is emitted by the UI that also pass the data to save.
Program execution has just started.
The ALU is waiting for user input.
Program execution is ended. If the emulator has been started in non-interactive way then all components have to shutdown.
A key has been pressed.
Emitted by: keyboard
Consumed by: virtually any component. Some react to keypress, other maps keypress to logical events
Kind: physical
*** TODO: provide a generic component description and how to implement a new one ***
The status component manages the status of the power, record and print program switches and the precision wheel. Any switch has its own model (a byte or a u8) and maps low-level input events into higher-level events that represent status transitions.
Any switch could have been implemented as an indipendent component. I found out that would be overkill and implemented all in the status component.
The distributed and event based architecture requires a status component to guarantee a single source of truth for system status.
This switch turns on the real computer and the emulator too. When the power key is pressed a SystemStatusChanged message will be sent to the system; the new status can be On or Off, depending on previous status. The message in relevant to the UI (switch rendering and lights) and to the status component itself. Consumes: Message::KeyPressed(Key::Power) Produces: Message::SystemStatusChanged(SystemStatus)
The reset key restore the system to an initial status. It is used
The print program switch, when on (in), directs the computer to print out the instructions stored in memory from its present location in the program to the next Stop instruction, whenever the Print key is depressed. Consumes: Message::KeyPressed(Key::PrintProgram) Produces: Message::PrintProgramSwitch(Status: bool)
The record program switch, when on (in), directs the computer to store instructions either in the memory from the keyboard, or onto a magnetic program card from the memory. The record program switch must be off (out) to load instructions from a magnetic program card into the memory.
Consumes: Message::KeyPressed(Key::RecordProgram)
Produces: Message::RecordProgramSwitch(Status: bool)
The decimal wheel determines the number of decimal places to which computations will be carried out in the A register and the decimal places in the printed output, except for results from the R register. Rolling up the wheel increase the precision. Rolling down decrease it. Consumes: Message::KeyPressed(Key::DecimalUp) Message::KeyPressed(Key::DecimalDown) Produces: Message::SetPrecision(u8)
The following table lists events managed by the status component, emitted events and related consumers.
| Originator | Event | Event | Consumer | | --- | --- | --- | --- | --- | | Keyboard component | Message::KeyPressed (Key::Power) | Message::SystemStatusChanged (SystemStatus) (1) | ALU, GUI | | Keyboard component | Message::KeyPressed (Key::Reset) | Message::SystemStatusChanged (SystemStatus::Ready) (2) | ALU, GUI, most components | | Keyboard component | Message::KeyPressed (Key::PrintProgram) | Message::PrintProgramSwitch (bool) | ALU (?), GUI | | Keyboard component | Message::KeyPressed (Key::RecordProgram) | Message::RecordProgramSwitch (bool) | ALU (?), GUI | | Keyboard component | Message::KeyPressed (Key::DecimalUp) | Message::SetPrecision (u8) | ALU, GUI | | Keyboard component | Message::KeyPressed (Key::DecimalDown) | Message::SetPrecision (u8) | ALU, GUI |
(1) Flips system status between on and off (2) If system is on then promote status to ready
This component is purely functional and does not map to an actual, physical device. It is used to stop the emulator when a program ends. It is meant to be used in tests or in batch scenarios. It must not be used when running in interactive way.
The component listen for the ProgramEnded message then sends an halt event to the system.
Consumes: Message::ProgramEnded
Produces: Message::Halt
A Printer consumes a Print or PrintLine message and writes text somewhere.
The printer is split in two halves:
Available providers are:
To define a new provider it is necessary to implement the PrintProvider trait.
Depending on the UI architecture, a separate print component may not be required at all. UI could implement the PrintProvider trait and consume print events directly.
Programs are stored on magnetic cards. Storage components allow to read and write external memory.
The emulator supports two kinds of cards:
The component provides two kinds of cards in the Card enum:
Following the idea that UI can dynamycally change card type, the component does not have the internal architecture of others. To be dynamic, cards are implemented in the Card enum. This architecture is required because which kind of card to use it is an option of the UI and could vary at runtime. As such it seems more natural than a static component/provider split.
Depending on the UI architecture, a storage component may not be required at all. The UI may consume storage events directly. In the future it may be replaced by a static omponent-provider architecture.
Keyboard component provides input to the emulator. It has a component-provider architecture that allow to statically set the required provider. To write a new provider you must implement the KeyboardProvider trait.
The component maps input (scripted keys, real keyboard input, UI clicks, whatever) to Message::KeyPressed(...) events.
Consumed event | Behavior |
---|---|
Message::ProgramStarted | Lock the keyboard |
Message::ProgramStopped | Unlock the keyboard |
Message::ProgramEnded | Unlock the keyboard |
Provider | Input source | Applicability |
---|---|---|
CliKeyboard | Command line | Interactive command line emulator |
ScriptKeyboard | Text file | Batch emulator |
TestKeyboard | Array of keys | Unit tests |
TODO
When the switch is in the off position, any input is disabled and the emulator is turned off; in order to turn the P101 on you need to move the switch to the ON position.
The general reset key erases all data and instructions from the computer and turns off the error light.
Tape advance advances the paper tape. This event is managed for emulator completeness but shold have no effect in a virtual environment.
The tape release lever enables precise finger-tip adjustment when changing tape rolls. This event is managed for emulator completeness but shold have no effect in a virtual environment.
The routine selection keys V, W, Y and Z direct the computer to the proper program or subroutine.
The numeric keyboard uses the ten-key entry system (1 2 3 4 5 6 7 8 9 0 . -) with provision for entry of a decimal point and a negative sign. Keyboard entries are automatically stored in the M register.
The clear entry key clears the entire keyboard entry. When keying in a program, a depression of the clear key will erase the last instruction that has been entered.
The start key restarts the computer in programmed operation and is used to code a stop instruction when keying in programs.
The register address keys A, B, C, D, E, F and R identify the corresponding registers. The operating register M has no keyboard identification since the computer automatically relates all instructions to the M register unless instructed otherwise.
The print key prints the contents of an addressed register.
The clear key clears the contents of an addressed register. When the computer is operated manually, a depression of this key will print the number in that register and clear it.
The transfer keys perform transfer operations between the storage registers and the operating registers. (Refer to discussion of transfer operations for the function of each transfer key.)
The arithmetic keys + - * / perform their indicated arithmetic function.
The keyboard release key reactivates a locked keyboard. If two or more keys are depressed simultaneously, the keyboard will lock to indicate a misoperation. Because the operator does not know what entry was accepted by the computer, after touching the Keyboard Release key the Clear Entry key (16) must next be depressed and the complete figure re-entered.
The GUI or a test emits a Message::CardRemoved message
The storage receives a Message::CardRemoved and ejects any inserted card.
TODO
Status components represent computer status to the user. They are an abstraction to be used as base for GUI-specific components. The system does not have any expectations for the GUI. In the following paragraphs is described the behavior that GUI components should have to conform to the actual P101. System by itself is GUI-implementation agnostic.
The error light indicator is on is two cases:
The correct performance (green) light indicates the computer is functioning properly. A steady light indicates that the computer is ready for an operator decision; a flickering light indicates the computer is executing programmed instructions and that the keyboard is locked.