Modular Computers the manual GitHub

Talking to devices

Your shell from A command shell can already reach every device on the bus. This page uses it on a redstone card: setting its output, taking its events, and running a program you write for your OS. The same steps work for any device: its page in Devices lists its methods.

What you need

The whole thing

A program for your OS, /blink.lua on your OS disk (beside /init.lua):

-- blink.lua: a program for the tiny OS (run /blink.lua 3): blinks the redstone card's north
-- face on and off as many times as asked, then returns to the shell. It uses the board as the
-- OS does, and the OS's print.
local FACE = "north"
local HALF = 0.5 -- seconds on, and seconds off

local times = tonumber(arg[1]) or 1

-- The first redstone card on the bus.
local card
for _, device in ipairs(board.list()) do
  if device.type == "redstone" then
    card = device.address
    break
  end
end
if not card then
  print("no redstone card")
  return
end

for i = 1, times do
  board.invoke(card, "set", {[FACE] = {powered = 15}})
  board.waitForInterrupt(HALF, "nothing") -- a sleep: no device is called "nothing"
  board.invoke(card, "set", {[FACE] = {powered = 0}})
  board.waitForInterrupt(HALF, "nothing")
  print("blink " .. i)
end

Download os-blink.lua

At your OS’s prompt:

# methods redstone
get([sides]): every face as {level ..., powered ...} by name ...
pull(): the oldest change to a face, from wherever it came, as {name, side, level, powered} ...
set(sides): sets each face named: powered, the signal it puts out (0 to 15) ...
# call redstone set {north = {powered = 15}}
{down = {level = 0, powered = 0}, east = ..., north = {level = 15, powered = 15}, ...}
# call redstone set {north = {powered = 0}}
...
# wait 1
exp:0
# call redstone pull
{level = 15, name = "redstone", powered = 15, side = "north"}
# run /blink.lua 3
blink 1
blink 2
blink 3

The lamp lights at the first call, goes dark at the second, and blinks three times with run.

Step by step

1. Find out what it can do

methods redstone asks the board for the card’s methods (board.methods) and each one’s line of documentation (board.doc). Every device describes itself this way, so methods works on a device you’ve never used: try it on sata:0 or eeprom.

2. Call a method

call redstone set {north = {powered = 15}} is the same as this line in a program:

board.invoke("exp:0", "set", {north = {powered = 15}})

set takes a table of faces, each with the signal to put out (powered, 0 to 15), and answers with every face as it is now: level is the signal there, powered this card’s own. Faces are north, south, east, west, up and down, or front, back, left and right from the case’s front (see Faces).

3. Take its events

A device with news raises its interrupt, and keeps the news until a program takes it. The redstone card keeps an event for every change to a face, whoever made it: your set, a lever, another card.

That’s the pattern for every device: wait for its interrupt, then call the method its page names to take what it has (pull for a redstone card or a sensor, read for a terminal, changes for a disk). Interrupts are level-triggered: a device’s stays raised while it has news, so nothing is missed between the wait and the take.

Flip a lever beside the case, then wait 1 and call redstone pull: the event’s level is the lever’s signal, and powered stays your card’s own (0), so you can tell a signal coming in from one your card puts out.

4. Run a program

run /blink.lua 3 loads /blink.lua from the boot disk and runs it with 3 as its argument (arg[1]). The program:

This is all a program is to your OS: a Lua file it loads and calls. In mcos, a program is far more (a process of its own, files, signals), but every one of those is code like your shell’s, built on the same board calls.

Where to go from here

Back to Your own OS.