Documentation

Select a topic Micro PinOS v1.0
📖

Select a topic from the sidebar

Documentation is loaded dynamically — choose any section to begin.

// Quick reference

Key Code Patterns

Real snippets from the framework — copy and adapt for your build.

Mega main loop
void loop() {
  readRS485();         // drain bus → queue
  processNextEvent();  // one event per pass
  updateGameLogic();   // state + timers
  updateSolenoids();   // millis() pulses
}

// RS485 frame format: "S<id>:<state>\n"
// e.g.  "S3:1\n" = switch 3, closed
Nano switch table
// pin | id | solPin | holdPin | ms | debounce
static const SwEntry SW[] = {
  // Type 2 — fires local coil immediately
  { 3, SW_SLINGSHOT_LEFT,  5, -1, 25, 5 },
  // Type 1 — sensor only, no coil
  { 7, SW_ROLLOVER_F,     -1, -1,  0, 10 },
  // Type 3 — dual wound flipper
  // (add #define DUAL_WOUND at top)
  { 4, SW_FLIPPER_LEFT,    5,  6, 30, 5 },
};
GameStyle interface
// Five functions — the entire interface
void gXInit()          { /* game start */    }
void gXBallReset()     { /* per-ball reset */}
void gXShot(int sw)    {
  if (tiltActive) return;
  switch (sw) {
    case SW_ROLLOVER_F:
      addScore(500);
      sendSound(SND_ROLLOVER);
      sendLight(LGT_LANE_F);
      break;
  }
}
void gXTimerTick()     { /* mode timers */   }
void gXBallDrain()     { /* bonus + done */  }
Send commands to secondary boards
// Wire format: "TYPE:PAYLOAD\n"

// Sound → Serial2
sendSound(SND_BUMPER);       // "SOUND:BUMPER\n"
sendSound(SND_JACKPOT);      // "SOUND:JACKPOT\n"

// Lights → Serial3
sendLight(LGT_LANE_F);       // "LIGHT:LANE_F\n"
sendLight(LGT_FRENZY_ON);    // "LIGHT:FRENZY_ON\n"

// Score display → Serial3
addScore(1000);              // "SCORE:<total>\n"

// Mode broadcast → all Nanos (Serial1/RS485)
broadcastNanoMode(MODE_FRENZY); // "N*:M:FRENZY\n"
Fire solenoids (non-blocking)
// All coil timing via millis() — never delay()
fireSolenoid(IDX_TROUGH, TROUGH_PULSE_MS); // 60ms
fireSolenoid(IDX_KNOCKER);                 // 30ms default
fireSolenoid(IDX_SLING_LEFT);

// Called every loop() pass — releases coils
void updateSolenoids() {
  unsigned long now = millis();
  for (int i = 0; i < NUM_SOLENOIDS; i++) {
    if (solenoids[i].active &&
        now >= solenoids[i].endMs) {
      digitalWrite(solenoids[i].pin, LOW);
      solenoids[i].active = false;
    }
  }
}
State machine transitions
enum GameState {
  STATE_ATTRACT,
  STATE_GAME_RUNNING,
  STATE_BALL_DRAIN,
  STATE_GAME_OVER
};

// startGame() — attract → running
void startGame(uint8_t style) {
  currentGame    = &gameStyles[style];
  credits--;
  score          = 0;
  ballsRemaining = BALLS_PER_GAME;
  currentGame->onInit();
  gameState = STATE_GAME_RUNNING;
  broadcastNanoMode(MODE_GAME);
  sendSound(SND_GAME_START);
  fireSolenoid(IDX_TROUGH, TROUGH_PULSE_MS);
}