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) 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 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 - 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 - RQ: set value - allow to change a value - RSP: set value (response to set value request) - 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) - 4K7/10K fuer Pull-up (I2C lines) - Kondensatoren: - 10 microF (fuer Spannungsregler) - 100nF (Abblockkondensatoren fuer Chips) - Chips: - HT7333 (3V3 Spannungsregler - 74LS21: Dual 4-Port AND Gate (OpenCollector Outputs) 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 (2479 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 Next: - read/write FLASH ; with temp1 ; AtTiny84 ; -------- ; VCC 1 14 GND ; PB0 2 13 PA0 ; PB1 3 12 PA1 COM-DATA ; /RESET PB3 4 11 PA2 ; KEY1 PB2 5 10 PA3 LED ; COM_ATTN PA7 6 9 PA4 TWI-SCL ; TWI-SDA PA6 7 8 PA5 ; -------- ; with temp2 ; AtTiny84 ; -------- ; VCC 1 14 GND ; PB0 2 13 PA0 ; PB1 3 12 PA1 COM-DATA ; /RESET PB3 4 11 PA2 OWI ; KEY1 PB2 5 10 PA3 LED ; COM_ATTN PA7 6 9 PA4 ; PA6 7 8 PA5 ; -------- ; with pwm ; AtTiny84 ; -------- ; VCC 1 14 GND ; PB0 2 13 PA0 ; FAN1-IN PB1 3 12 PA1 COM-DATA ; /RESET PB3 4 11 PA2 OWI ; KEY1 PB2 5 10 PA3 LED ; COM_ATTN PA7 6 9 PA4 FAN2-IN ; PWM1-OUT PA6 7 8 PA5 PWM2-OUT ; -------- ; with optic door/window sensors ; AtTiny84 ; -------- ; VCC 1 14 GND ; PB0 2 13 PA0 DOOR-ADC1 ; DOOR-ADC2 PB1 3 12 PA1 COM-DATA ; /RESET PB3 4 11 PA2 ; KEY1 PB2 5 10 PA3 LED ; COM_ATTN PA7 6 9 PA4 TWI-SCL ; TWI-SDA PA6 7 8 PA5 ; -------- ; HT7333 ; ------ ; Vin +-------+ ; = C (10 uF) ; Gnd +-------+ ; = C (10 uF) ; Vout +-------+ ; ------ Timer_Run TODO: - disable interrupts - first handle internal counters and sample into internal flags - enable interrupts - call handlers (every10s etc) according to flags