Files
aqhomecontrol/TODO
2023-02-02 00:45:52 +01:00

545 lines
14 KiB
Plaintext

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
- 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