I just added the STM8 eForth MODBUS pre-release 0.16 that not only supports FC-2 "Read Discrete Inputs" but also actually reads C0135 "4-Relay Board" inputs (finally).
Unlike writing board outputs with OUT! words for reading inputs have never been part of the STM8 eForth core. It's been a while since output words coded in assembler were moved into boardcore.inc. Since the new modular build supports binary GitHub releases with Forth code there is no reason anymore for coding board support words in assembler.
I just added IN@ in Forth for supporting low-active inputs (NPN in PLC lingo):
\ opcode: rotate C left through TOS lsb
: RLC(1,X) $6901 , ; IMMEDIATE
\ read C0135 inputs - connect INx to GND to get a "1"
: IN@ (
-1 \ inputs are "NPN" (in PLC speak), start with all bits 1
[ ( IN4 ) PC_IDR 6 ]BC RLC(1,X) \ some simple STM8 assembly
[ ( IN3 ) PC_IDR 7 ]BC RLC(1,X) \ to load bits to C
[ ( IN2 ) PD_IDR 2 ]BC RLC(1,X) \ and rotate them into the
[ ( IN1 ) PD_IDR 3 ]BC RLC(1,X) \ Top Of Stack low-byte
Ok, I have to admit that this is almost assembler but IN@ is more readable than an implementation in C. I like C but low level routines, and the code they produce, are a frequent source of concerns, compiler bug reports, #pragmas, syntax extendsions and idioms without adding the least bit to portability (even if your intent is to exchange compilers, not hardware).
Using this is as simple as always: IN@ will return a bitmap containing the inputs.
The following "program" will activate a relay if the corresponding input is pulled low:
\ copy inputs to outputs
: doit ( -- )
IN@ ( n ) OUT!
' doit BG ! \ run in background
The background task makes this task surprisingly easy. Note: everything ( in brackets ) and after "\" are comments.
Adding a simple state machine already allows doing some interesting things.