mirror of https://github.com/thelsing/knx
H8I8O Example (#210)
Firmware for the H8I8O that allows configuring pins as input, output or PWM output in a similar way to the original.pull/215/head
parent
5dc3d7666b
commit
8af9121f6f
4 changed files with 2447 additions and 0 deletions
@ -0,0 +1,210 @@ |
||||
#include <Arduino.h> |
||||
#include <knx.h> |
||||
|
||||
#define NUMIOS 18 |
||||
|
||||
#define goInputOnOff(i) knx.getGroupObject(i + 1) |
||||
#define goOutputOnOff(i) knx.getGroupObject(i + 1 + NUMIOS) |
||||
#define goOutputScaling(i) knx.getGroupObject(i + 1 + NUMIOS * 2) |
||||
#define goOutputOnOffStatus(i) knx.getGroupObject(i + 1 + NUMIOS * 3) |
||||
#define goOutputScalingStatus(i) knx.getGroupObject(i + 1 + NUMIOS * 4) |
||||
|
||||
typedef enum { |
||||
CONFIG_NONE = 0, |
||||
CONFIG_IN = 1, |
||||
CONFIG_IN_TOGGLE = 2, |
||||
CONFIG_IN_TOGGLE_ON = 3, |
||||
CONFIG_OUT = 4, |
||||
CONFIG_OUT_ON = 5, |
||||
CONFIG_OUT_PWM = 6, |
||||
CONFIG_OUT_PWM_ON = 7, |
||||
} config_t; |
||||
|
||||
inline void isrIn(uint8_t pin, uint8_t toggle); |
||||
|
||||
// workaround for the weird Arduino interrupt handling
|
||||
#define ISR_IN(NUM, TOGGLE) void isrIn##NUM##_##TOGGLE(){isrIn(NUM, TOGGLE);} |
||||
ISR_IN(0,0); |
||||
ISR_IN(1,0); |
||||
ISR_IN(2,0); |
||||
ISR_IN(3,0); |
||||
ISR_IN(4,0); |
||||
ISR_IN(5,0); |
||||
ISR_IN(6,0); |
||||
ISR_IN(7,0); |
||||
ISR_IN(8,0); |
||||
ISR_IN(9,0); |
||||
ISR_IN(10,0); |
||||
ISR_IN(11,0); |
||||
ISR_IN(12,0); |
||||
ISR_IN(13,0); |
||||
ISR_IN(14,0); |
||||
ISR_IN(15,0); |
||||
ISR_IN(16,0); |
||||
ISR_IN(17,0); |
||||
ISR_IN(0,1); |
||||
ISR_IN(1,1); |
||||
ISR_IN(2,1); |
||||
ISR_IN(3,1); |
||||
ISR_IN(4,1); |
||||
ISR_IN(5,1); |
||||
ISR_IN(6,1); |
||||
ISR_IN(7,1); |
||||
ISR_IN(8,1); |
||||
ISR_IN(9,1); |
||||
ISR_IN(10,1); |
||||
ISR_IN(11,1); |
||||
ISR_IN(12,1); |
||||
ISR_IN(13,1); |
||||
ISR_IN(14,1); |
||||
ISR_IN(15,1); |
||||
ISR_IN(16,1); |
||||
ISR_IN(17,1); |
||||
|
||||
const uint32_t pinTbl[NUMIOS] = {PA15, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PC13, PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PB0}; |
||||
void (*inCbTbl[NUMIOS * 2])(void) = {isrIn0_0, isrIn1_0, isrIn2_0, isrIn3_0, isrIn4_0, isrIn5_0, isrIn6_0, isrIn7_0, isrIn8_0, isrIn9_0, isrIn10_0, isrIn11_0, isrIn12_0, isrIn13_0, isrIn14_0, isrIn15_0, isrIn16_0, isrIn17_0, isrIn0_1, isrIn1_1, isrIn2_1, isrIn3_1, isrIn4_1, isrIn5_1, isrIn6_1, isrIn7_1, isrIn8_1, isrIn9_1, isrIn10_1, isrIn11_1, isrIn12_1, isrIn13_1, isrIn14_1, isrIn15_1, isrIn16_1, isrIn17_1}; |
||||
volatile uint16_t val[NUMIOS]; |
||||
uint32_t lastEvent[NUMIOS]; |
||||
|
||||
// callback for OnOff events from KNX
|
||||
void outOnOff(GroupObject& go) |
||||
{ |
||||
uint8_t pin = go.asap() - 1 - NUMIOS; |
||||
val[pin] = go.value(); |
||||
val[pin] &= 1; |
||||
digitalWrite(pinTbl[pin], val[pin]); |
||||
goOutputOnOffStatus(pin).value(val[pin]); |
||||
} |
||||
|
||||
// callback for OnOff events from KNX on PWM pins
|
||||
void outOnOffPWM(GroupObject& go) |
||||
{ |
||||
uint8_t pin = go.asap() - 1 - NUMIOS; |
||||
uint8_t tmp; |
||||
if(go.value()){ |
||||
val[pin] |= 0x100; |
||||
analogWrite(pinTbl[pin], val[pin] & 0xff); |
||||
}else{ |
||||
val[pin] &= 0xff; |
||||
analogWrite(pinTbl[pin], 0); |
||||
} |
||||
tmp = val[pin] >> 8; |
||||
goOutputOnOffStatus(pin).value(tmp); |
||||
} |
||||
|
||||
// callback for 0-100% events from KNX
|
||||
void outScaling(GroupObject& go) |
||||
{ |
||||
uint8_t pin = go.asap() - NUMIOS * 2 - 1; |
||||
uint8_t tmp; |
||||
if(val[pin] > 0xFF){ |
||||
tmp = *go.valueRef(); |
||||
val[pin] = tmp | 1 << 8; |
||||
analogWrite(pinTbl[pin], val[pin] & 0xff); |
||||
}else{ |
||||
tmp = *go.valueRef(); |
||||
val[pin] = tmp; |
||||
} |
||||
*goOutputScalingStatus(pin).valueRef() = tmp; |
||||
goOutputScalingStatus(pin).objectWritten(); |
||||
} |
||||
|
||||
// callback for input interrupts
|
||||
inline void isrIn(uint8_t pin, uint8_t toggle) |
||||
{ |
||||
uint32_t diff = millis() - lastEvent[pin]; |
||||
if (diff >= 50 && diff <= 500){ |
||||
if(toggle){ |
||||
val[pin]++; |
||||
}else{ |
||||
val[pin] = digitalRead(pinTbl[pin]); |
||||
} |
||||
val[pin] &= 1; |
||||
goInputOnOff(pin).value(val[pin]); |
||||
} |
||||
|
||||
lastEvent[pin] = millis(); |
||||
} |
||||
|
||||
void setup() |
||||
{ |
||||
// read adress table, association table, groupobject table and parameters from eeprom
|
||||
knx.readMemory(); |
||||
|
||||
// print values of parameters if device is already configured
|
||||
if (knx.configured()) |
||||
{ |
||||
uint8_t progIn = knx.paramByte(0); // programming input
|
||||
uint8_t progLed = knx.paramByte(1); // programming LED
|
||||
|
||||
for(uint8_t i = 0; i < NUMIOS; i++){ |
||||
config_t config = (config_t) knx.paramByte(i + 2); |
||||
// loop through all the pins and configure them correctly
|
||||
switch(config){ |
||||
case CONFIG_IN: |
||||
pinMode(pinTbl[i], INPUT_PULLUP); |
||||
if(progIn = i + 1){ |
||||
knx.buttonPin(pinTbl[i]); |
||||
}else{ |
||||
goInputOnOff(i).dataPointType(DPT_Switch); |
||||
#if (ARDUINO_API_VERSION >= 10200) |
||||
attachInterrupt(digitalPinToInterrupt(pinTbl[i]), inCbTbl[i], (PinStatus)CHANGE); |
||||
#else |
||||
attachInterrupt(digitalPinToInterrupt(pinTbl[i]), inCbTbl[i], CHANGE); |
||||
#endif |
||||
} |
||||
break; |
||||
case CONFIG_IN_TOGGLE: |
||||
case CONFIG_IN_TOGGLE_ON: |
||||
goInputOnOff(i).dataPointType(DPT_Switch); |
||||
val[i] = config == CONFIG_IN_TOGGLE_ON; |
||||
pinMode(pinTbl[i], INPUT_PULLUP); |
||||
#if (ARDUINO_API_VERSION >= 10200) |
||||
attachInterrupt(digitalPinToInterrupt(pinTbl[i]), inCbTbl[i + NUMIOS], (PinStatus)CHANGE); |
||||
#else |
||||
attachInterrupt(digitalPinToInterrupt(pinTbl[i]), inCbTbl[i + NUMIOS], CHANGE); |
||||
#endif |
||||
break; |
||||
case CONFIG_OUT: |
||||
case CONFIG_OUT_ON: |
||||
pinMode(pinTbl[i], OUTPUT); |
||||
val[i] = config == CONFIG_OUT_ON; |
||||
digitalWrite(pinTbl[i], val[i]); |
||||
if(progLed = i + 1){ |
||||
knx.ledPin(pinTbl[i]); |
||||
}else{ |
||||
goOutputOnOff(i).dataPointType(DPT_Switch); |
||||
goOutputOnOff(i).callback(outOnOff); |
||||
goOutputOnOffStatus(i).dataPointType(DPT_Switch); |
||||
} |
||||
break; |
||||
case CONFIG_OUT_PWM: |
||||
case CONFIG_OUT_PWM_ON: |
||||
pinMode(pinTbl[i], OUTPUT); |
||||
val[i] = config == CONFIG_OUT_PWM_ON ? 0 : 0x1ff; |
||||
analogWrite(pinTbl[i], val[i] & 0xff); |
||||
goOutputOnOff(i).dataPointType(DPT_Switch); |
||||
goOutputOnOff(i).callback(outOnOffPWM); |
||||
goOutputOnOffStatus(i).dataPointType(DPT_Switch); |
||||
goOutputScaling(i).dataPointType(DPT_Scaling); |
||||
goOutputScaling(i).callback(outScaling); |
||||
goOutputScalingStatus(i).dataPointType(DPT_Scaling); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
// start the framework.
|
||||
knx.start(); |
||||
} |
||||
|
||||
void loop() |
||||
{ |
||||
// don't delay here too much. Otherwise you might lose packages or mess up the timing with ETS
|
||||
knx.loop(); |
||||
|
||||
// only run the application code if the device was configured with ETS
|
||||
if (!knx.configured()) |
||||
return; |
||||
} |
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,39 @@ |
||||
;PlatformIO Project Configuration File |
||||
; |
||||
; Build options: build flags, source filter |
||||
; Upload options: custom upload port, speed and extra flags |
||||
; Library options: dependencies, extra library storages |
||||
; Advanced options: extra scripting |
||||
; |
||||
; Please visit documentation for the other options and examples |
||||
; https://docs.platformio.org/page/projectconf.html |
||||
[platformio] |
||||
; We have to keep libdeps dir out the project directory otherwise, |
||||
; library scanner seems to have issues so compilation fails |
||||
libdeps_dir = /tmp/libdeps |
||||
src_dir = . |
||||
|
||||
;--- STM32/GD32 --- |
||||
[env:h8i8o] |
||||
platform = ststm32 |
||||
board = genericSTM32F103CB |
||||
framework = arduino |
||||
; We consider that the this projects is opened within its project directory |
||||
; while working with VS Code. |
||||
lib_extra_dirs = ../../../ |
||||
|
||||
lib_deps = |
||||
knx |
||||
|
||||
build_flags = |
||||
-DENABLE_HWSERIAL1 |
||||
-DPIN_SERIAL1_TX=PA9 |
||||
-DPIN_SERIAL1_RX=PA10 |
||||
-DKNX_SERIAL=Serial1 |
||||
-DKNX_BUTTON=PA11 |
||||
-DKNX_LED=PA12 |
||||
-DMASK_VERSION=0x07B0 |
||||
-DKNX_NO_PRINT |
||||
-Wno-unknown-pragmas |
||||
|
||||
extra_scripts = ../scripts/stm32rdu.py |
Loading…
Reference in new issue