Skip to content

Commit

Permalink
Merge pull request #21 from TG9541/C0135-inputs
Browse files Browse the repository at this point in the history
fixes #20: add C0135 inputs
  • Loading branch information
TG9541 authored Apr 24, 2020
2 parents 762cd03 + 73e8ce7 commit 482ca11
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 24 deletions.
34 changes: 34 additions & 0 deletions C0135/IN@
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
\ C0135 4-Relay board: read low side inputs - License MIT refer to STM8 eForth

\ This is close to the iron
\res MCU: STM8S105
\res export PC_IDR PC_CR1 PD_IDR PD_CR1

\ copy bit to C flag, set/res bit
#require ]BC
#require ]B!
#require WIPE

\ opcode: rotate C left through TOS lsb
: RLC(1,X) $6901 , ; IMMEDIATE

NVM
\ read C0135 inputs - connect INx to GND to get a "1"
: IN@ ( -- n )
-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
NOT
;

\ init C0135 inputs
: IN@INIT ( -- )
\ let's assume that Px_DDR are still in reset state
[ ( IN1 ) 1 PD_CR1 3 ]B! \ set pull-up for NPN (low side) switches
[ ( IN2 ) 1 PD_CR1 2 ]B!
[ ( IN3 ) 1 PC_CR1 7 ]B!
[ ( IN4 ) 1 PC_CR1 6 ]B!
;
WIPE RAM
24 changes: 20 additions & 4 deletions C0135/board.fs
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
\ C0135 STM8 eForth MODBUS board code

( Hint for non-Forthers )
\ - this and the above are comments
\ - @ means "read" and ! means "write"
\ - : means "compile", [ switches to "interpret", ] back and ; "end compile"
\ - #require, \res, etc are e4thcom or codeload.py keywords

\ compile MODBUS server and protocol words
#require MBSERVER

\ We need the C0135 "read inputs" word
#require C0135/IN@

\ we're in RAM mode: load "scaffolding words"
#require :NVM
#require WIPE
#require LOCK
#require ULOCK
#require 'IDLE

\ temporary symbols
\ define temporary constants
$4000 CONSTANT EE_NODE
$4002 CONSTANT EE_BAUD

\ now compile to Flash ROM
NVM
\ from here on compile to Flash ROM
#require OUT!
\ headerless code Preparation Handler
:NVM
IN@ inputs !
;NVM ( xt-pre ) \ compile time: keep this eXecution Token on the stack

\ headerless code Action Handler
:NVM
coils @ OUT!
;NVM ( xt-act ) \ compile time: keep this eXecution Token on the stack
;NVM ( xt-act ) \ and also this

\ --- MODBUS server startup
: init ( -- )
\ register the xt (see above) as the MODBUS Action Handler
( xt-act ) LITERAL mbact !
( xt-pre ) LITERAL mbpre !

\ Holding C0135 key "S2" while start-up resets Node-ID and baud rate
BKEY IF
Expand All @@ -41,6 +54,9 @@ NVM
UNTIL
THEN

\ initialize C0135 inputs
IN@INIT

\ initialize MODBUS "coils" and outputs
0 coils ! 0 OUT!

Expand Down
8 changes: 4 additions & 4 deletions MBSERVER
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ NVM \ compile to Flash memory from here on

\ FC01 handler
:NVM ( -- )
[ ( xt xth ) SWAP ] LITERAL 1 ( xth xt bpu ) mbread
[ ( xt xth ) SWAP ] LITERAL 1 ( xt bpu ) mbread
;NVM ( xth ) 1 FC>XT !


Expand All @@ -53,7 +53,7 @@ NVM \ compile to Flash memory from here on

\ FC02 handler
:NVM ( -- )
[ ( xt xth ) SWAP ] LITERAL 1 ( xth xt bpu ) mbread
[ ( xt xth ) SWAP ] LITERAL 1 ( xt bpu ) mbread
;NVM ( xth ) 2 FC>XT !


Expand All @@ -77,7 +77,7 @@ NVM \ compile to Flash memory from here on

\ FC03 handler
:NVM ( -- )
[ ( xt xth ) SWAP ] LITERAL 16 ( xth xt bpu ) mbread
[ ( xt xth ) SWAP ] LITERAL 16 ( xt bpu ) mbread
;NVM ( xth ) 3 FC>XT !


Expand All @@ -90,7 +90,7 @@ NVM \ compile to Flash memory from here on

\ FC04 handler
:NVM ( -- )
[ ( xt xth ) SWAP ] LITERAL 16 ( xth xt bpu ) mbread
[ ( xt xth ) SWAP ] LITERAL 16 ( xt bpu ) mbread
;NVM ( xth ) 4 FC>XT !


Expand Down
34 changes: 18 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# stm8ef-modbus
[![Travis-CI](https://travis-ci.org/TG9541/stm8ef-modbus.svg)](https://travis-ci.org/TG9541/stm8ef-modbus)

This repository provides a lightweight MODBUS RTU implementation with [STM8 eForth](https://github.com/TG9541/stm8ef/wiki) for "wired" control nodes, e.g. for home automation. The is intended for low-cost STM8S 8bit µCs like the STM8S003F3P6 with 8K Flash and 1K RAM.
This repository provides a lightweight MODBUS RTU implementation with [STM8 eForth](https://github.com/TG9541/stm8ef/wiki) for "wired" control nodes, e.g. for home automation. The main target is low-cost STM8S 8bit µCs like the STM8S003F3P6 with 8K Flash and 1K RAM.

The MODBUS I/O Node implementation for the low-cost [C0135 4-Relay RTU module][C0135] serves as a demonstrator, and in [GitHub Releases](https://github.com/TG9541/stm8ef-modbus/releases) you'll find a ready-to-use binary.

Using STM8 Forth for MODBUS has many advantages: while the implementation is very compact it gives applications access to many advanced architectural features like independent I/O-locic execution in the background, a CLI (command line interface). The Forth compiler is included and you can literally change the code through the built-in console while your board is communicating with the MODBUS host!
Using STM8 Forth for MODBUS has some advantages: the implementation is very compact and it gives applications access to many advanced architecture features like "I/O-locic execution in the background" or a CLI (command line interface).

The C0135 MODBUS implementation covers basic FCs: it's a subset of [MODBUS V1.1b](http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf) common in simple I/O nodes. It's easy to write code for other FCs. It's also simple to turn the board in something like an independent controller for window blinds: the MODBUS host only commands "open" or "closed", not "up" and "down". Local control code can help to make home automation much more robust and reactive.
The Forth compiler/interpreter is part of the binary you can literally change the code while your board is communicating with the MODBUS host!

Right now there is no MODBUS master implementation but the code in this repository can be re-used to write one.
The MODBUS RTU implementation covers basic FCs: it's a subset of [MODBUS V1.1b](http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf) common in simple I/O nodes. It's easy to write code for other FCs. It's also simple to turn the board in something like an independent controller for window blinds: the MODBUS host only commands "open" or "closed", not "up" and "down". Local control code can help to make home automation much more robust and reactive.

## Supported Boards

Expand All @@ -22,7 +22,7 @@ The [C0135 board][C0135] is the default target.

You can simply transfer the ready-made binary to your board with a cheap "ST-LINK V2" dongle, or run `make` to flash the STM8 eForth C0135 code.

Using a diode and a cheap USB-TTL dongle you can [get a console][TWOWIRE].
Using a diode and a cheap USB-TTL dongle you can [get a console][TWOWIRE] (this means the MODBUS node *is* a computer, a bit like the console of a VIC20 in the old days ;-) ).

[TWOWIRE]: https://github.com/TG9541/stm8ef/wiki/STM8-eForth-Programming-Tools#using-a-serial-interface-for-2-wire-communication

Expand All @@ -39,28 +39,30 @@ It's easy to build custom targets, e.g. using the $0.80 [MINDEV board](https://g

![MINDEV](https://camo.githubusercontent.com/82bd480f176951de9a469e134f543a6570f48597/68747470733a2f2f616530312e616c6963646e2e636f6d2f6b662f485442314e6642615056585858586263587058587136785846585858362f357063732d6c6f742d53544d3853313033463350362d73797374656d2d626f6172642d53544d38532d53544d382d646576656c6f706d656e742d626f6172642d6d696e696d756d2d636f72652d626f6172642e6a70675f323230783232302e6a7067)

When using PB5 for RS485 direction control (-> `BUSCTRL`) the C0135 code can be used.
When using PB5 for RS485 direction control (-> `BUSCTRL`) the C0135 code can be used unchanged.

## Supported MODBUS Function Codes

`MBSERVER` contains MODBUS function plug-ins with the following function codes (FC):

FC | Description | Support
-|-|-
**1**| **Read Coils** | implemented
**2** | **Read Discrete Inputs** | implemented (limit to "8bit aligned")
**3** | **Read Holding Registers** | implemented (variables in RAM)
**1**| **Read Coils** | implemented ++
**2** | **Read Discrete Inputs** | implemented ++
**3** | **Read Holding Registers** | implemented (variables or EEPROM)
**4** | **Read Input Registers** | implemented
**5** | **Write Single Coil** | implemented
**6** | **Write Single (Holding) Register** | implemented
**15** | **Write Multiple Coils** | implemented
15 | Write Multiple Coils | see [issue #19](https://github.com/TG9541/stm8ef-modbus/issues/19)
16 | Write Multiple Registers | partial

An example for diagnostic functions is in `main.fs` and a way to load communication properties from the EEPROM is implemented in `C0135/board.fs`.
++: *currently limited to "8bit aligned start address", e.g. 0, 8, 16*

A working example with Node-ID and Baud Rate stored in EEPROM is implemented in `C0135/board.fs`. An example that shows how to develop minimal servers with FC handlers from scratch using the Forth console is in `main.fs`.

## Installation

This project uses the STM8 eForth "Modular Build" feature: `make depend` fetches a STM8 eForth release.
This project uses the STM8 eForth "Modular Build" feature: `make depend` fetches the STM8 eForth release defined in the `Makefile`.

On a Linux system common dependencies are e.g. GAWK, MAKE and Python. SDCC needs to be installed. It's also possible to use `tg9541/docker-sdcc` in a Docker container (refer to `.travis.yml` for details).

Expand All @@ -70,7 +72,7 @@ Please refer to the [Installation Instructions](https://github.com/TG9541/stm8ef

## Console

While MODBUS communication uses the STM8S UART, the Forth console communicates through a half-duplex simulated RS232 interface through the `PD1/SWIM` GPIO pin (and a diode). This is made possible by the SWIMCOM STM8 eForth "stock binary" which the makefile pulls from the STM8 eForth Releases. Other CLI communication options, e.g. using simulated full-duplex RxD-TxD lines, require building a custom STM8 eForth binary.
While MODBUS communication uses the STM8S UART, the Forth console communicates through a half-duplex simulated RS232 interface through the `PD1/SWIM` GPIO pin (and a diode). This is made possible by the SWIMCOM STM8 eForth "stock binary" which the makefile pulls from the STM8 eForth Releases. Other CLI communication options, e.g. using simulated full-duplex RxD-TxD lines, require building a custom STM8 eForth binary. It's also possible to use an STM8S High Density device with two UARTs like the STM8S207RBT6.

Please refer to the [STM8 eForth Wiki](https://github.com/TG9541/stm8ef/wiki/STM8S-Value-Line-Gadgets#other-target-boards) to learn more about half-duplex CLI communication options and preferred terminal programs.

Expand All @@ -81,19 +83,19 @@ The software architecture separates hardware abstraction and application in simp
Layer|Source file|Description
-|-|-
5|`main.fs` or `{BOARD}/board.fs`|configuration and application layer
4|`MBSERVER`|MODBUS FC plug-ins
4|`MBSERVER`|MODBUS FC plug-ins (optional)
3|`MBPROTO`|MODBUS protocol layer
2|`UARTISR`|buffered UART communication
1|`BUSCTRL`|bus access (i.e. RS485 direction control)
0|STM8 eForth|lightweight interactive multi-tasking OS

The different concerns are separeted in the code and FC handlers can be changed through the CLI without restarting the application!

The code is organized in the following execution domains:
* interrupt service routines for buffered MODBUS communication
* fixed-rate background task for I/O logic (asynchronous to MODBUS)
* foreground "idle mode" MODBUS protocol handler
* foreground command line interface (CLI) through independent COM port provided by STM8 eForth
* handlers for MODBUS I/O: `mbpre` for input, `mbact` for output actions

The different concerns are separeted in the code - FC handlers can be changed through the CLI without restarting the application!

Please refer to the [how-to in the wiki](https://github.com/TG9541/stm8ef-modbus/wiki/HowTo) and don't hesitate to open an [issue](https://github.com/TG9541/stm8ef-modbus/issues) if you have questions!

0 comments on commit 482ca11

Please sign in to comment.