Create: Computing AgesDoc Brass
Périphériques

Lecteur de cartes Jacquard

Le séquenceur à cartes perforées : où il en est dans son paquet, les quatre puissances de redstone qu'il donne, et les trous de chaque carte qu'il contient.

Le Lecteur de cartes Jacquard est la tête du métier à tisser de Jacquard (1804), qui lisait une chaîne de cartes perforées : la première machine programmable. Un arbre le fait tourner par le dessous, et à chaque quart de tour il lit la ligne suivante de ses cartes et donne quatre puissances de redstone, une sur chaque côté. Tout seul, il fait tourner une séquence d'usine sans aucun ordinateur. Un ordinateur relié au lecteur suit cette séquence : quelle carte et quelle ligne il lit, ce que donne chaque côté, et les trous de chaque carte qu'il contient.

Brass
local lecteur = peripheral.find("card_reader")
local p = lecteur.position()
print("carte " .. p.card .. " sur " .. p.cards .. ", ligne " .. p.row)
Méthodes
lecteur.position()Où en est le lecteur dans son paquet, en comptant à partir de 1, comme le montrent les lunettes :
lecteur.outputs()La puissance de redstone que donne chaque côté en ce moment, d'après la ligne lue. Les quatre valent 0 tant que le lecteur est vide ou bloqué.
lecteur.card(n)Les trous de la carte n, sous forme d'une liste de 12 nombres, un par ligne. nil quand le lecteur contient moins de n cartes. Un nombre à virgule arrête le programme avec bad argument #1 to 'card' (number has no integer representation).

Fonctionnement

Les cartes. Une Carte perforée vierge devient une Carte perforée dans la Poinçonneuse : 12 lignes de 16 trous. Faites un clic droit sur le lecteur avec une Carte perforée pour l'ajouter au bout de la chaîne, jusqu'à 9 cartes ; un clic droit à main vide reprend la dernière. Le lecteur lit ses cartes de la première case jusqu'à la première case vide.

Les lignes. Chaque quart de tour de l'arbre passe à la ligne suivante. Après la ligne 12 vient la ligne 1 de la carte suivante, et après la dernière carte, de nouveau la première. Plus l'arbre tourne vite, plus la séquence est rapide : à 16 tr/min, un peu plus d'une ligne par seconde ; à 256 tr/min, environ 17. Le sens de rotation ne compte pas.

Le bloquer. Un signal de redstone venu du bloc du dessus (un levier posé sur le lecteur, ou de la poudre de redstone dessus) bloque le lecteur : il revient à la carte 1, ligne 1, donne 0 sur ses quatre côtés, et cesse de lire jusqu'à ce que le signal disparaisse.

Les quatre côtés. L'avant est la face qui vous regardait quand vous avez posé le lecteur. La droite et la gauche sont celles du lecteur lui-même, comme pour une personne en face de vous : sa droite est à votre gauche. Posez une lampe de redstone de chaque côté pour vérifier.

Les trous. Dans la Poinçonneuse, chaque ligne a quatre groupes de quatre trous, marqués Avant, Droite, Arrière et Gauche. Les trous d'un groupe valent 8, 4, 2 et 1 : la puissance donnée de ce côté est la somme des trous perforés, de 0 (aucun trou) à 15 (les quatre). Les Lunettes d'ingénieur montrent la carte, la ligne et les quatre puissances.

Le joindre depuis un ordinateur. Posez le lecteur contre une face de l'ordinateur ou, à partir du Mini-ordinateur, contre un Câble de données de son réseau, où il prend un nom comme card_reader@120,64,-35. Il tourne et il contient des cartes : c'est donc aussi un bloc cinétique (lecteur.speed()) et un inventaire de 9 cases, une carte chacune. Voir Périphériques.

Quand le lecteur a disparu, chaque méthode arrête le programme avec card reader removed ; quand son chunk n'est pas chargé, avec peripheral is not loaded.

Suivre la séquence

#

lecteur.position()

→ table

Où en est le lecteur dans son paquet, en comptant à partir de 1, comme le montrent les lunettes :

Renvoie
table
{card =, row =, cards =, reset =}
champcontenu
cardla carte en cours de lecture, de 1 à cards ; 0 quand le lecteur est vide
rowla ligne en cours de lecture, de 1 à 12
cardsle nombre de cartes enchaînées, de 0 à 9
resettrue tant que la redstone du dessus bloque le lecteur sur sa première ligne
Brass
local lecteur = peripheral.find("card_reader")
local p = lecteur.position()
if p.cards == 0 then
  print("mettez des cartes perforées dans le lecteur")
elseif p.reset then
  print("bloqué sur la première ligne par la redstone du dessus")
else
  print("carte " .. p.card .. "/" .. p.cards .. ", ligne " .. p.row .. "/12")
end

Voir aussi card_reader.outputs() card_reader.card()

#

lecteur.outputs()

→ table

La puissance de redstone que donne chaque côté en ce moment, d'après la ligne lue. Les quatre valent 0 tant que le lecteur est vide ou bloqué.

Renvoie
table
{front =, right =, back =, left =}, chacune une puissance de redstone de 0 à 15

Les côtés sont ceux du lecteur lui-même (voir « Les quatre côtés » plus haut). Ce programme affiche chaque nouvelle ligne à son arrivée, les quatre puissances dans cet ordre :

Brass
local lecteur = peripheral.find("card_reader")
local derniere = ""
while true do
  local o = lecteur.outputs()
  local ligne = o.front .. " " .. o.right .. " " .. o.back .. " " .. o.left
  if ligne ~= derniere then
    print(ligne)
    derniere = ligne
  end
  sleep(0.05)
end

Quand deux lignes qui se suivent donnent les mêmes puissances, seule la première s'affiche.

Voir aussi card_reader.position() card_reader.card()

Les cartes

#

lecteur.card(n)

→ table|nil

Les trous de la carte n, sous forme d'une liste de 12 nombres, un par ligne. nil quand le lecteur contient moins de n cartes. Un nombre à virgule arrête le programme avec bad argument #1 to 'card' (number has no integer representation).

Paramètres
n number
la place de la carte dans la chaîne, à partir de 1
Renvoie
table|nil
les 12 lignes de la carte, un nombre chacune ; nil quand il n'y a pas de carte n

Comment une ligne devient un nombre. Chaque trou perforé ajoute sa valeur. Dans le groupe Avant, les trous ajoutent 8, 4, 2 et 1, comme les marque la Poinçonneuse ; dans le groupe Droite, 16 fois plus ; dans le groupe Arrière, 256 fois plus ; dans le groupe Gauche, 4096 fois plus. Une ligne vaut donc

avant + 16 × droite + 256 × arrière + 4096 × gauche

de 0 (une ligne vierge) à 65535 (les 16 trous). Vu comme un nombre binaire de 16 bits, le bit c (c de 0 à 15) vaut 1 quand son trou est perforé : les bits 0 à 3 sont la puissance de l'avant, 4 à 7 celle de la droite, 8 à 11 celle de l'arrière et 12 à 15 celle de la gauche.

Brass n'a pas d'opérateurs sur les bits : // (la division arrondie vers le bas) et % (le reste) décomposent une ligne.

Brass
local function puissances(ligne)
  return {
    avant = ligne % 16,
    droite = (ligne // 16) % 16,
    arriere = (ligne // 256) % 16,
    gauche = (ligne // 4096) % 16,
  }
end

local p = puissances(16138)
print(p.avant, p.droite, p.arriere, p.gauche)

16138 vaut 10 + 256 × 15 + 4096 × 3 : ce programme affiche 10, 0, 15 et 3. Un seul trou se lit de la même façon : le trou c est perforé quand ligne // 2 ^ c % 2 vaut 1, donc ligne // 2 ^ 4 % 2 == 1 teste le trou qui vaut 1 dans le groupe Droite.

Tout le paquet, carte après carte, avec les quatre puissances de chaque ligne :

Brass
local lecteur = peripheral.find("card_reader")
for n = 1, lecteur.position().cards do
  print("carte " .. n)
  print("lig. avant droite arr. gau.")
  local lignes = lecteur.card(n)
  for l = 1, 12 do
    local ligne = lignes[l]
    print(string.format("%4d %5d %6d %4d %4d", l, ligne % 16, (ligne // 16) % 16, (ligne // 256) % 16, (ligne // 4096) % 16))
  end
end

Voir aussi card_reader.position()

Exemple : un tableau de bord du séquenceur

Un écran à côté du métier : l'étape en cours de lecture, et une barre pour chaque côté. Le lecteur fait tourner l'usine tout seul ; l'ordinateur ne fait que montrer ce qu'il fait.

Brass
local lecteur = peripheral.find("card_reader")
local COTES = {front = "avant", right = "droite", back = "arrière", left = "gauche"}
local ORDRE = {"front", "right", "back", "left"}
while true do
  local p = lecteur.position()
  local o = lecteur.outputs()
  term.clear()
  term.set_cursor(1, 1)
  print("LECTEUR JACQUARD")
  if p.cards == 0 then
    print("aucune carte")
  elseif p.reset then
    print("bloqué sur la première ligne")
  else
    print("carte " .. p.card .. "/" .. p.cards .. ", ligne " .. p.row .. "/12")
  end
  for _, cote in ipairs(ORDRE) do
    print(string.format("%-7s %2d %s", COTES[cote], o[cote], string.rep("#", o[cote])))
  end
  sleep(0.1)
end