


MODULE_INFO
- descr:
  - one MODULE_INFO for every module
  - can share code (e.g. use multiple MODULE_INFOs for different pins in PinOut module)
- def:
  - name[16]
  - id
  - handlerFunctionAddr()
- code:
  .equ MODULE_INFO_HANDLER_LO = 0
  .equ MODULE_INFO_HANDLER_HI = 1
  .equ MODULE_INFO_ID         = 2
  .equ MODULE_INFO_NAME       = 4
  .equ MODULE_INFO_SIZE       = 12


SIGNAL_TABLE:
- descr:
  - one table for every signal a module can emit
- def:
  - array of SLOT objects (end of array: 0x0000)


SLOT:
- descr:
  - one SLOT for every module which is waiting for this signal
- def:
  - MODULE_INFO *modInfoPtr (16 bit)
  - signalIdForCaller (8 bit)
  - signalIdForCallee (8 bit)




Initial module:
- OS
  - sent signals:
    - init
    - fini
  - receivable signals:
    - sleep
    - hardReset
    - softReset


Other modules:
- Timer
  - sent signals:
    - 1Hz
    - 10Hz
    - 100Hz

- PinOut
  - receivable signals:
    - setValue
    - setOnDuration
    - setOffDuration
  - sent signals:
    - none




Module_EmitSignal:
- params:
  - senderId (8 bit)                                                     R16
  - signalIdForSender (8 bit, unique in the realm of the sender)         R17
  - slotIdForRecipient (8 bit, unique in the realm of the recipient)     R18
  - paramLo  (8 bit) R26 (YL)
  - paramHi  (8 bit) R27 (YH)
  - recipientModule R30 (ZL), R31 (ZH) (16 bit)


Notes:
- R24 und R25: 16 register (supports ADIW and SBIW)
- for RAM access: R26-R31 (X, Y, Z)
- for flash memory access: R0 and Z (R30/31)
- in INT: use R15 for flags
- for everything else: R1-R14
- LDI only for upper 16 regs


Generic signals from OS module:
- init
- fini
- request (REQUEST flag for a module can be set by an interrupt handler to request that the corresponding
           module be called as soon as the event handler loop is reached)


<moduledef name="os" ramSizeNeeded="2"> <!-- 16 bit request mask, maximum 16 modules for now -->
  <signals>
    <signal name="1Hz" />
  </signals>
  
  <interrupts>
    <irq id="EXT_INT0" handler="AQOS_Timer_Int0" />
  </interrupts>
  
</moduledef>




<moduledef name="timer">
  <signals>
    <signal name="100Hz" />
    <signal name="10Hz" />
    <signal name="1Hz" />
  </signals>
  
  <interrupts>
    <irq id="EXT_INT0" handler="AQOS_Timer_Int0" />
  </interrupts>
  
</moduledef>


<moduledef name="togglePort" ramSizeNeeded="2" >
  <depModules>
    <depModule name="timer" />
  </depModules>
  
  
  <signals>
    <signal name="100Hz" />
    <signal name="10Hz" />
    <signal name="1Hz" />
  </signals>

  <slots>
    <slot name="timer10Hz" />
    <slot name="setValue" />
    <slot name="setOnDuration" />
    <slot name="setOffDuration" />
  </slots>
  
  <connections>
    <connect module="timer" signalId=10Hz" slotId="timer10Hz" />
  </connections>
  
</moduledef>


<moduledef name="inputPinChange" ramSizeNeeded="8"> <!-- current state of ports a..d and change masks -->
  <signals>
    <signal name="aPortChanged" />
    <signal name="bPortChanged" />
    <signal name="cPortChanged" />
    <signal name="dPortChanged" />
  </signals>
  
  <interrupts>
    <irq id="PCI0" handler="AQOS_InputPinChange_PCI0" />
    <irq id="PCI1" handler="AQOS_InputPinChange_PCI1" />
  </interrupts>

  <slots>
    <slot name="request" />
  </slots>


irq handler:
  - for every port:
    - is port change mask 0? -> SET new mask, otherwise OR new mask with old mask
      -> gracefully handling overrun (e.g. a new PIN change before the previous one was handled)

req handler:
  - for every port:
    - is port change mask 0? -> emit aPortChanged(currentPortValue, portChangeMask), clear mask

</moduledef>




File format:

IRQ-Table

.include "os/rqhandlers.inc"
.include "timer/irqhandlers.inc"
.include "toggleport/irqhandlers.inc"


.equ MODULE_ID_OS         = 0
.equ MODULE_ID_TIMER      = 1
.equ MODULE_ID_TOGGLEPORT = 2


.equ TIMER_USE_100Hz      = 1
.equ TIMER_USE_10Hz       = 1
.equ TIMER_USE_10z        = 1

; in file timer/modinfo.inc

; timer module
modInfoTimer:
  .db "TIMER  ", 0         ; name
  .db MODULE_ID_TIMER, 0   ; id, reserved byte (0)
  .dw timerSignalHandler   ; handler

.equ TIMER_SIG_1HZ = 1

.equ TIMER_SLOT_INIT = 0
.equ TIMER_SLOT_FINI = 1



; in file toggleport/module.inc

; toggleport module
.equ TOGGLEPORT_SLOT_OS_INIT   = 0
.equ TOGGLEPORT_SLOT_OS_FINI   = 1
.equ TOGGLEPORT_SLOT_TIMER_1HZ = 2




; in main source file

; signal table for timer
timerSignalTable:
  .db TIMER_SIG_1HZ, TOGGLEPORT_SLOT_TIMER_1HZ, LOW(modInfoTogglePort), HIGH(modInfoTogglePort)
  .db 0, 0, 0, 0 ; last entry





Assembler:
- generate automatic list of modified registers


.object test1 {
  .sram {
    Testdata:
      .bytes 16
  }
  
  .eprom {
  }
  
  .code {
  }
}



function test1 {
  ld r16, 10
l1:
    dec r16
  brne l1
  ret
}





Hardware:

AtTiny 84
=========
                                                       ----------
                                                   VCC + 1   14 +   GND
              (PCINT8,  XTAL1, CLKI)               PB0 + 2   13 +   PA0 (ADC0, AREF,           PCINT0)   IN/OUT
              (PCINT9,  XTAL2)                     PB1 + 3   12 +   PA1 (ADC1, AIN0,           PCINT1)   WAN-DATA
              (PCINT11, RESET, dW)                 PB3 + 4   11 +   PA2 (ADC2, AIN1,           PCINT2)   IN/OUT   [LED (red)]
KEY->IRQ_PCI1 (PCINT10, INT0, OC0A, CKOUT)         PB2 + 5   10 +   PA3 (ADC3, T0,             PCINT3)   LED (green)
WAN-ATTN(PCI0)(PCINT7,  ICP1, OC0B, ADC7)          PA7 + 6    9 +   PA4 (ADC4, USCK, SCL, T1,  PCINT4)   I2C, SPI
     I2C, SPI (PCINT6,  OC1A, SDA, MOSI, DI, ADC6) PA6 + 7    8 +   PA5 (ADC5, DO, MISO, OC1B, PCINT5)   SPI
                                                       ----------


AtTiny 85
=========
                                                       ----------
              (PCINT5, /RESET, ADC0, dW)           PB5 + 1    8 +   VCC
WAN-ATTN      (PCINT3, XTAL1, CLKI, /OC1B, ADC3)   PB3 + 2    7 +   PB2 (SCK, USCK, SCL, ADC1, T0, INT0, PCINT2)
WAN-DATA      (PCINT4, XTAL2, CLKO, OC1B, ADC2)    PB4 + 3    6 +   PB1 (MISO, DO, AIN1, OC0B, OC1A, PCINT1)
                                                   GND + 4    5 +   PB0 (MOSI, DI, SDA, AIN0, OC0A, /OC1A, AREF, PCINT0)
                                                       ----------



ADC   = ADC Input Channel
AREF  = External Analog Reference
PCINT = Pin Change Interrupt
AIN   = Analog Comparator Input (0=positive, 1=negative input)
T0    = Timer/Counter0 Clock Source
T1    = Timer/Counter1 Clock Source
USCK  = USI Clock (Three Wire Mode)
SCL   = USI Clock (I2C Mode=
DO    = USI Data Output (Three Wire Mode)
MISO  = SPI Master Data Input / Slave Data Output (Three Wire Mode)
OC0A  = Timer/Counter0 Compare Match A Output
OC0B  = Timer/Counter0 Compare Match B Output
OC1A  = Timer/Counter1 Compare Match A Output
OC1B  = Timer/Counter1 Compare Match B Output
SDA   = USI Data Input (I2C Mode)
MOSI  = SPI Data Master Output/Slave Data Input (Three Wire Mode)
ICP1  = Timer/Counter1 Input Capture Pin



WAN-ATTN -> irq PCI0
KEY      -> irq PCI1
PA0 -> in/out1
PA2 -> in/out2
PA3 -> LED
PA4-6: I2C, SPI



WAN-Communication:

WAN-Protocol (UART 9600bps 8N1)


104us pro bit bei 9600bps, about 1040us per byte, about 8.3ms per 8 bytes

               52us  104us    104us    104us    104us    104us    104us    104us    104us    104us    104us
            INACTIVE START    0        1        2        3        4        5        6        7        STOP        INACTIVE
- DATA     ~11111111 00000000 00000000 00000000 11111111 00000000 11111111 00000000 11111111 00000000 11111111    11111111 11~
- /ACTIVE  ~11100000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000    11111111 11~
                     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX (repeat for every byte)



Sensors:
- Erd-Feuchtigkeitssensor: 
  https://www.mouser.de/ProductDetail/M5Stack/U019?qs=sGAEpiMZZMu2rInN%2FZRmFkkq%2FqtywxsmOLlgBBfclSVLB6YzCank4Q%3D%3D


- rename WAN -> inc (inter-node-communication)
- INC messages:
  - 1 byte : dest address                                                      [not saved]
  - 1 byte : msg length (not including dest address, msg length and xor byte)  [not saved]
  - n bytes: data
  - 1 byte : XOR checksum                                                      [not saved]

Packet in buffer:
- 1 byte: buffer length
- 1 byte: flags
- 1 byte: dest address
- 1 byte: msg data


- receivePacket:
  - recv dest address
    - matches?
      - no: finished
  - recv msg size
    - too big?
      - yes: ABORT
    - alloc buffer (msg size +1)
      - error?
        - yes: ABORT
    - write to buffer: size+0x80 (0x80: READ)
  - for every msg size byte: receive byte
  - receive XOR byte
  - check XOR checksum
    - 0?
      - no: ABORT, DeallocBufferBack




Infrastructure, what's next
===========================

- build PC module to read and write control messages
- make WAN code in AVR stable
- implement command to write debug messages to PC via WAN

- node
  - unit (e.g. environment, presence, door, power)    [defines per unit type, use uint8_t values]
    - value (e.g. temp, humidity, pressure, light)

- addresses:
  - 8-bits total, but:
    - bit 7=0: bit 0-6 contains a node address (i.e. max 127 node devices)
    - bit 7=1, bit 6=0: bits 0-5 contain id of a group:
      - nodes with window/door status
      - nodes with alarm output (e.g. horn, bell or or sms)
      - nodes with environmental readouts (temp, humidity etc.)
    - 240+: special ids
      - 252: timekeeper node
      - 253: id of database node
      - 254: id of a router node to upper layers (e.g. room -> appartement -> floor -> house)
      - 255: broadcast (every node)
    - 0: only unassigned nodes (used when assigning an address)

- nodes:
  - database node
    - contains a list of known nodes and their modules and addresses on a bus
  - router node
    - forwards upwards in the hierarchy (e.g. from room to appartement level)

- commands:
  - ping
  - pong
  - announce device
    - used to assign a 8-bit device id on a bus
    - needs a 8-byte serial number for the device
  - assign device id
    - response from a database node to "announce device"
  - announce module
    - make information about a module on a node available to a central node (or other interested nodes)
  - announce value
    - make info about data available
  - value data
    - announce changes in a given module
  - set value
    - allow to change a value
  - request value info
    - make the node send the current value of a given module


Bauteile fuer Platine:
- Widerstaende:
  - 1K fuer LEDs
  - 10K fuer Pull-up (UART lines)
- Kondensatoren:
  - 10 microF (fuer Spannungsregler)
  - 100nF (Abblockkondensatoren fuer Chips)


Memory Layout:
- 0x0000-0x003f: Reset and IRQ vectors
- 0x0040       : 8 bytes node id (never overwritten)
- 0x0048       : 2 bytes maintenance system version
- 0x004a-0x004f: reserved
- 0x0050-0x09ff: maintenance system  (2485 bytes)
- 0x0a00-0x0a3f: working system; reset and IRQ vectors
- 0x0a40-0x0a4f: reserved (later: pointer to version etc)
- 0x0a50-end   : rest of working system


Interrupt-Vektoren:
- bei aktivem maintenance system:
  - rjmp PC+0x050
- bei aktivem working system:
  - rjmp PC+0xa00



Interface Data (WAN):
- 1 Byte interface num (0-3)
- 1 Byte flags
- 1 Byte address
- child node addresses (for routers):
  - 1 Byte start
  - 1 Byte end
- 1 Byte bit mask for data bit
- 1 Byte address for data input port
- 1 Byte address for data output port
- 1 Byte address for data DDR port
- 1 Byte bit mask for ATTN bit
- 1 Byte address for ATTN input port
- 1 Byte address for ATTN output port
- 1 Byte address for ATTN DDR port


