Epics@GSI Webhome

Multi-purpose control API implementation on HadCon



HadCon is a general purpose IO module for detector and experiment control as well as for small data acquisition systems.


(HADControl general purpose board) Since its first application has been a power monitor for the Hades Shower Detector it has been formerly introduced and well known as HadShoPoMo (Hades Shower Power Monitor (HADControl/HadShoPoMo general purpose board).

HadCon has an SoC on-board, ETRAX 100LX MCM 4+16 from AXIS (Wikipedia: en/de) - which will be discontinued, see the new HadCon2.

Running a standard Linux the Etrax provides "Connectivity to the world" via TCP/IP.
On the other side it connects via its internal serial interface to an ATMEL AT90CAN128 microcontroller and optionally to an Xilinx CPLD.
Via this junction the ATMEL provides a multitude of possible connections to field buses and general I/O ports.

EPICS base and its applications, modules, and extensions can be cross-compiled to run on Etrax Axis' CRIS architecture (see section Architecture: ETRAX's CRIS by AXIS

  • Summarizing:
    • CPU: AXIS ETRAX 100LX MCM 4+16
    • Microcontroller: ATMEL AT90CAN128
      • I2C (internal)
        • 2 × 4-channel 8-Bit DAC - Digital-to-Analog Converter
      • CANbus
        • galvanically isolated CAN - High-speed CAN Transceiver
          • optional external power supply
      • SPI
      • ADCs
      • RS232
      • 32 digital I/Os
    • CPLD: Xilinx XCR3064XL-6CS48C
    • 2 × Rotary Code Switches, hexadecimal coding
    • Ericsson PME 5218TS switching regulator for up to 6A 3.3V power usable for other boards
    • full EPICS support

This projects' objective is to combine all existing HadCon (HADControl general purpose board) implementations into one μController code for its ATMEL AT90CAN128:
  • CANbus (based on the thesis and work of L.Fouedjou, see Project Page)
  • One-Wire bus implementation
    • ADC
    • DAC
    • Temperature
    • Switches
  • HadCon's internals
    • DACs
    • ADCs
  • ...




  • HadCon
    • Power supply, 6V
    • Kernel programming: Sergey Yurevic, HADES
    • Schematic
    • Micro-controller: AT90CAN128
    • CPU: AXIS ETRAX 100LX MCM 4+16
    • CPLD: 64 Macrocell CPLD Xilinx (XC)R3064XL
    • Tweaks:
        Set fuses
        First time you are programming a new hadcon board with “Olimex” (s.below) you have to “set fuses” (up-to-now I don't now what this means) by issuing from your cross compiling computer the following sequence:
        $> avarice -c 0,1,0,4 --jtag /dev/ttyUSB0 -B 1000000 -W ff19e0
        Bridge Flip-flop to increase ATMEL_CLOCK to 10MHz
        to be able to transmit up to baud rates of 115200 you have to manipulate the hardware of the hadcon.
        The clock signal of the oscillator X1 is 20 MHz. It is scaled down by two flip-flops (UFF1, UFF2) first to 10 MHz and then to 5 MHz.
        Now 10 MHz are needed
        Therefore UFF2 has to be bridged or short-cut, i.e.
        1. pin 5 of UFF2 has to be disconnected from its pad and removed
        2. A cable has to be soldered connecting pin 1 of UFF2 to the solder pad of pin 5
        DHCP / NFS mount
        Etrax tries to NFS mount directories extracted from the DHCP information:
        1. At start-up the ETRAX board with its kernel sends an DHCP broadcast request with its MAC adress
        2. An special (private) DHCP server returns the needed network settings
        3. But the secondary DNS server address is taken as mount point to mount files from
        4. more about contact Sergey Yurevich at GSI
  • AVR-USB-JTAG Connector (olimex)
    • ADAN2: Connector
      • ADAN2 schematic,pdf: ADAN2 Measuring adapter
        • missing connection on pin 1 and 2 in the schematic, they connect one-to-one
        • final connection :
          AVR-JTAG-USB pin ADAN2 in pin JTAG hadcon in
          AVR name HadCon name
          TCK 1 9 9 TCK
          GND 2 8 8 GND
          TDO 3 7 7 TDIN
          VREF 4 - -  
          TMS 5 1 1 TMS
          NSRST 6 - -  
          VCC 7 5 5 +5V
          NTRST 8 - -  
          TDI 9 3 3 TDOUT
          GND 10 10 10 GND
    • make sure the user accessing the AVR-USB-JTAG has sufficient permissions
      • suse-linux:
        • user should be member of group dialout
        • before accessing change group by issuing the command: newgrp dialout
          • TODO: Check: are there smarter alteratives ???
  • Devices to connect to
    • CAN
    • 1-Wire
    • Registers
    • ...


    HadCon - Documentation


    Code Repositories

        The code is available on the gitlab repository of GSI
        • repository: https://git.gsi.de/HadCon2/Firmware/HadCon2
          • !HadCon2 : Microcontroller Code
            • Branches: (q.v. Git Workflow)
              • 4.x.y: version
              • master: (link to subversion)
              • dev: branch to consolidate before committing/merging into master
        • Access
          • read: https
          • further access on request, ask P.Zumbruch
            • needs login access to git.gsi.de to become a member

Tar Balls & ELFs
    Tar ball, including ELFs
        x.0 x.1 x.2 x.3 x.4 x.5 x.6
      1.x 1.0
      2.x 2.0 2.1
      3.x 3.0 3.1
      4.x 4.0 4.1 4.2 4.3 4.4 4.5  
            4.3.1 4.4.1 4.5.1 4.6.1
            4.3.2 4.4.2   4.6.2

    HadCon2 - ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped
        x.0 x.1 x.2 x.3 x.4 x.5 x.6
      4.x       4.3.2 - hadcon1      
            4.3.2 - hadcon2      
            4.3.3 - hadcon1      
            4.3.3 - hadcon2      
              4.4.1 - hadcon1    
              4.4.1 - hadcon2    

      • Programming:
        • using avrdude you can program: (asuming HadCon2 jtag chain)
          $> avrdude -v -P /dev/ttyUSBx -pc128 -c jtagmkI -x jtagchain=0,1,0,8 -Uflash:w:<hadcon>.elf
          • Don't forget setting fuses, to be done when HadCon2 is programmed the first time:
            $> avrdude -v -P /dev/ttyUSBx -pc128 -c jtagmkI -x jtagchain=0,1,0,8 -Uefuse:w:0xff:m -Uhfuse:w:0x19:m -Ulfuse:w:0xe0:m
        HadCon Note
        In case of HadCon(1) use jtagchain=0,1,0,4 instead
        • using obsolete avarice you can program: (asuming HadCon2 jtag chain)
          avarice -c 0,1,0,8 --jtag /dev/ttyUSBx -B 1000000 --erase --program --file <hadcon>.elf
          • Don't forget setting fuses, to be done when HadCon2 is programmed the first time:
            avarice -c 0,1,0,8 --jtag /dev/ttyUSBx -B 1000000 -W ff19e0
        HadCon Note
        In case of HadCon(1) use jtagchain=0,1,0,4 instead



Supported devices
    Family code Device and datasheet
    10h pdf DS18S20 1-Wire Parasite-Power Digital Thermometer
    28h pdf DS18B20 1-Wire Programmable Resolution 1-Wire Digital Thermometer
    20h pdf DS2450 1-Wire Quad A/D Converter
    3Ah pdf DS2413 1-Wire Dual Channel Addressable Switch
    05h pdf DS2405 1-Wire Addressable Switch
    29h pdf DS2408 1-Wire 8-Channel Addressable Switch


-- PeterZumbruch - 2020-08-04


The basic operation principle is that
  • HadCon's ETRAX processor communicates via the serial interface (/dev/ttyS1) with the μController sending and receiving keyword based ASCII streams/strings (see Protocol below for details)
  • μController provides the communication with the (external) devices

  • In general a command and its possible response e.g. HELP is sent/retrieved from the ETRAX to the ATMEL with
    $> /mnt/flash/API-Master "HELP"
    or by listening to /dev/ttyS1 while sending the command to the same device
    $> cat </dev/ttyS1 &
    $> echo >/dev/ttyS1 "HELP"

The following two sections, describe
  • first the connections from the ATMEL to the possible device classes, and
  • in the second part the corresponding protocols commands and responses of the API seen from the controlling ETRAX via the serial bus.

Device classes

    CAN bus

    • Acting as a CAN bus master, using connector JCAN1
    • up-to-now:
      • only 11-Bit-Identifier, "Base frame format" (CAN 2.0A)
      • 29-Bit-Identifier, "Extended frame format" (CAN 2.0B) extension on request
    • Sending, receiving, subscription to channels defined by ID and optionally by a mask (default 0)


    • access to up to 8 individual 1-wire chains/buses connected to connector JDINOUT2, pins 1-8
    • global commands
      • list all devices
      • determine parasitic devices
      • TODO:
        • missing, not yet implemented, but prepared
          • 1-wire atomic commands
    • family specific commands
      • temperature sensor
      • adc
      • switches (1/2/8(TODO))

    Internal ADC

    • read values
      Threshold Relay
      • switching of output pin depending on input of ADC
      • configurable input
        • TODO: add documentation

    I2C - a.k.a. Two Wire Bus

    • not yet implemented in version 3.1 but in progress, comes with 4.0
    • direct access only to internal devices foreseen (DAC)
      • but a bit of soldering may widen its horizon.

      • 2 times 4 channels DAC,
      • output connector JDAC1 and partly JPS

    Internals of microcontroller

    • help, all and command specific
    • debugging
      • increasing verbosity,
      • mask available
    • status (show)
      • memory status (initially unused, unused, free)
      • available predefined error statements
    • direct register access read/write
    • JTAG enable/disable (handle with care)

    ... to be extended



    CPU → μController
    The communication consists of short command keywords, e.g. HELP, SEND, SPI, etc, followed by (optional) arguments or sub commands

    <Keyword, 3-5 letters, (capital letters)> <Message>

    • NOTE: from version 4.6.1 on all command keywords are case insensitive
    • string termination (automatically) by <LF> or <CR>

    μController → CPU

    The following answers can occur
    • RECV followed by the sent command keyword and the 'result'
    • nothing, usually send actions
      • can be made more verbose by increasing the debug level via DEBG <debug level>, <debug level> > 0
        • RECV <literal acknowledge>*
    • ERRx in case of an error
      • ERRx <Error number> <Error description>
      • ERRx <Error number> <Error description> *** "<Additional Information>"
      • ERRx "<Command>" <Error number> <Error description>
      • ERRx "<Command>" <Error number> <Error description> *** "<Additional Information>"
      • where 'x' can be
        • G : global errors
        • A : api errors, e.g. typos, wrong arguments, inputs, syntax, out of limits, etc.
        • C : CAN related global errors
        • M : CAN related message box errors
        • T : I²C errors, Two-Wire-Interface
        • U : undefined


    $ HELP : will give an overview list of available commands, e.g. :
        RECV HELP --- available commands are:
        RECV HELP --- SEND : send can message
        RECV HELP ---           SEND CAN-ID ID-Range [RTR <nBytes> D0 .. D7]
        RECV HELP --- SUBS : unsubscribe can id/mask
        RECV HELP ---           SUBS CAN-ID ID-Range
        RECV HELP --- USUB : unsubscribe can id/mask
        RECV HELP ---           USUB CAN-ID ID-Range
        RECV HELP --- RGWR : write register
        RECV HELP ---           RGWR <Register> <Value>
        RECV HELP --- RGRE : read register
        RECV HELP ---           RGRE <Register>
        RECV HELP --- RADC : AVR ADCs
        RECV HELP ---           RADC [<ADC Channel>]
        RECV HELP --- OWAD : 1-wire ADC
        RECV HELP ---           OWAD [ID [flag_conv [flag_init]]]
        RECV HELP --- OWDS : 1-wire double switch
        RECV HELP ---           OWDS [ID]
        RECV HELP --- INIT : (re)init of system
        RECV HELP --- OWLS : 1-wire list devices
        RECV HELP ---           OWLS [<Family Code>]
        RECV HELP --- OWSS : 1-wire single switch ([ID] not implemented)
        RECV HELP ---           OWSS [ID]
        RECV HELP --- RSET : reset via watchdog
        RECV HELP --- PING : 
        RECV HELP --- OWTP : 1-wire temperature
        RECV HELP ---           OWTP [ID [flag_conv [flag_init]]
        RECV HELP ---           OWTP <command_keyword> [arguments]]
        RECV HELP --- OWSP : one-wire set active pins/bus mask
        RECV HELP ---           OWSP <bus mask>
        RECV HELP --- CANT : CAN send message
        RECV HELP ---           CANT CAN-ID ID-Range [RTR <nBytes> D0 .. D7]
        RECV HELP --- CANS : CAN subscribe
        RECV HELP ---           CANS CAN-ID ID-Range
        RECV HELP --- CANU : CAN unsubscribe
        RECV HELP ---           CANU CAN-ID ID-Range
        RECV HELP --- DBGL : set/get debug level
        RECV HELP ---           DBGL [level]
        RECV HELP --- DBGM : set/get debug system mask
        RECV HELP ---           DBGM [mask]
        RECV HELP --- JTAG : set/get JTAG availability, switch off/enable 4 more ADC channels
        RECV HELP ---           JTAG [0|1]
        RECV HELP --- HELP : help
        RECV HELP ---           HELP [CMND]
        RECV HELP ---           HELP <mode>
        RECV HELP --- OWRP : 1-wire read active pins/bus mask
        RECV HELP --- DEBG : set/get debug level and mask
        RECV HELP ---           DEBG [level [mask]]
        RECV HELP --- PARA : parasitic device presence test
        RECV HELP --- SHOW : show (internal) settings
        RECV HELP ---           SHOW [key_word]
        RECV HELP --- OWSA : 1-wire API settings
        RECV HELP ---           OWSA <command_key_word> [arguments] 
        RECV HELP --- TWIS : I2C access
        RECV HELP ---           TWIS <0|1> <I2C address> <data length> <byte1 ... byte8>
        RECV HELP --- I2C  : I2C access
        RECV HELP ---           I2C <0|1> <I2C address> <data length> <byte1 ... byte8>
        RECV HELP --- RLTH : relay threshold
        RECV HELP ---           RLTH [command_key_word] <value>
        RECV HELP --- SPI  : experimental SPI master (slave)
        RECV HELP ---           SPI [data]
        RECV HELP ---           SPI <cmd> <arguments>
        RECV HELP --- GNWR : waveform generator write data
        RECV HELP ---           GNWR <address> <data>
        RECV HELP --- GNRE : waveform generator read data
        RECV HELP ---           GNRE <address>
        RECV HELP --- OW8S : 1-wire octal switches
        RECV HELP ---           OW8S [ID [value]]
        RECV HELP --- VERS : code version

    A more detailed command description you'll get by using the command:
    HELP <command>

-- PeterZumbruch - 2020-11-09 - 12:09


      Keyword Action Format Description Comments
      Send CAN Message SEND <CAN Message-ID> <ID-Range> [<RTR> <Length> <Data0 ... Data7>]
      CANT <CAN Message-ID> <ID-Range> [<RTR> <Length> <Data0 ... Data7>]

      RECV <MOB-number> <CAN Message-ID> <ID-Range> [<RTR> <Length> <Data0 ... Data7>]

      future response:
      RECV <CAN Message-ID> <ID-Range> [<RTR> <Length> <Data0 ... Data7>]
      Message-ID: CAN Message Identifier (hex)
      ID-Range: used as mask on Message IDs (hex)
      RTR: sets Remote Transmission Request Mode
      Length: number of data bytes to send (max: 8)
      Data 0...7: 0 to 8 data bytes (hex) MOB-number: index of receiving MOB (Message Object Blocks) in CAN controller
      Subscribe to Message-IDs SUBS <CAN Message-ID> <ID-Range>
      CANS <CAN Message-ID> <ID-Range>

      Subscribe to react on (a range of) CAN Messages
      Message-ID: CAN Message Identifier (hex)
      ID-Range: used as mask on Message IDs (hex)
      TODO: look to code, has to be clarified
      Unsubscribe from Message-IDs USUB <CAN Message-ID> <ID-Range>
      CANU <CAN Message-ID> <ID-Range>

      Unsubscribe from reacting on (a range of) CAN Messages
      Message-ID: CAN Message Identifier (hex)
      ID-Range: used as mask on Message IDs (hex)
      TODO: look to code, has to be clarified
      CAN CAN commands CAN <sub command> [ <arguments>> ... ]

      Replacing above commands by sub commoands TODO:

-- PeterZumbruch - 2020-11-09 - 12:08


-- PeterZumbruch - 2020-11-09 - 12:15


      available since version: 4.6.3
      Channel numbers
      The Channel numbers 0..7 follow the signal naming (DACOUTx, q.v. HadCon2/DAC) and are therefore shifted by -1 compared to the connector pin numeration from pin 1 to pin 8. The remaining pin 9 and 10 are ground. (q.v. connector assignment)

      1. DAC : return all DACs value
      2. DAC <CHANNEL> : return current DAC value
        • <CHANNEL>: 0 - 7
      3. DAC: <CHANNEL> <VALUE_mV> : set current DAC output to (approx.) wanted voltage
        • <CHANNEL>: 0 - 7
        • <VALUE_mV> - 0 - 3300 mV
          • alert: The actual resulting value might differ, due to the 8bit conversion binning of 3300mV / 255 ≈ 12,94 mV

        The output is the same for all commands:
        RECV DAC <CHANNEL> <VALUE_mV> <VALUE_HEX> [undefined]
        • <CHANNEL> : 0 - 7
        • <VALUE_mV> : 0 - 3300 mV, undefined → -1
        • <VALUE_HEX> : 0x00 - 0xFF, undefined → 0x100
        • undefined: since there is no readback, values are undefined until a value is set,
          • exception: after a power up, channels are set to 0V.
        In case you are using the command DAC , you will get the above for each channel from 0 to 7 in a separate line.

-- PeterZumbruch - 2020-11-09 - 12:16


-- PeterZumbruch - 2020-11-09 - 12:05



    RGWR <Register> <Value>

    <Register> : the register address has to be written in hexadecimal

    <Value> : here has to be written the new register value in hexadecimal

    Example command:
    ( toggling LEDs, by writing 1 to the PING0-PING5 registers while DDRG are set to outputs )
    send: RGRE 32
    receive: RECV RGRE 32 1c (11100)
    send: RGWR 32 7
    receive: RECV RGWR 7: value 1b has been written and readback does not match (1b)
    (since PINs are outputs)
    send: RGRE 32
    receinve: RECV RGRE 32 1b

-- PeterZumbruch - 2020-11-09 - 12:06


    I2C <0|1> <I2C address> <data length> <byte1 ... byte8>

    <0|1> : used to execute write or read operation. This is the Least Significant Bit (LSB) from the I2C address byte.

    <I2C address> : Here has to be written the hexadecimal value on the address byte, which is shifted to right with one bit. The reason for the right shift is because, the lsb bit ist already used in the first field, where the working operation is choosen.

    <data length> : data length

    <byte1 ... byte8> : data

    Example command:
    send: I2C O 70 1 08
    receive: RECV I2C 0 70 01 08 -OK-

-- PeterZumbruch - 2020-11-09 - 12:19


-- PeterZumbruch - 2020-11-09

last updated status & plans (-- PeterZumbruch - 13 Jul 2011)

current version: 4.3

  • 1-wire:
    • OWTP (temperature), OWAD (adc), OWLS (list devices) seems to work
      • according to the manual OWTP delivers reasonable values 25 to 30
    • OWAD in use and no complains
    • single ID access to the commands
    • 1-wire OWDS (read and write)
    • PARA parasitic mode check
    • optimize temperature conversion n_bus * 750 ms -> 1*750ms, make it optional
      • also done for adc
  • RLTH, threshold triggered relay
  • RADC, internal ADC readout
  • API:
  • CAN bus:
    • co-work with Florian Feldbauer, Univerity of Bochum
  • Atmel
    • RGWR, RGRE, register access
    • JTAG
  • I2C / Two Wire
    • TWIS
  • co build with HadCon2 (F.Brabetz)

near future version: 4.4

  • Request to implement DS2408 8-Channel Addressable Switch, by RPC/HADES/Coimbra
    • OW8S

future versions:

  • TWIS incl. subcommands for setting parameters
  • 1-wire elementary commands implementation, as subcommands
  • 1-wire OWxS switch:
    • OWxS: combine OWDS, OWSS, OW8S into a single command
  • ?? 1-wire: optionally: split temperature conversion into an automatic task initiated every (5-10) seconds, (maybe) blocking 1-wire bus for 750 ms, but not the
  • API settings command: APIC command value(s) or combine with SHOW command
  • check warnings
  • other possible devices
    • organizing local ADC support
      • including (already but rudimentary) existing relay / state machine control ( min < value < max )
  • clean-up
    • merge available commands into sub-commands
      • OWxx=, RGxx, RLxx
    • improve HELP content
  • modularize code to jump table of structure of functions (execute, help, ...) per command represented by its index
    • get rid of huge switch/case structures
    • input/output buffer for USART
  • ...

Meanwhile ...

Due to several request I had to develop different features in different branches. The main task is now to merge all these projects into one, where this is its poor-mans backup tarball.

-- PeterZumbruch - 21 Mar 2013

Topic attachments
I Attachment Action Size Date Who Comment
SCHEMATIC1_PAGE1.pdfpdf SCHEMATIC1_PAGE1.pdf manage 14 K 2010-03-12 - 11:33 PeterZumbruch ADAN2 Measuring adapter
avr-mem.shsh avr-mem.sh manage 5 K 2010-04-01 - 11:12 PeterZumbruch avr-mem (original from http://www.mikrocontroller.net/topic/52953 http://www.mikrocontroller.net/attachment/18841/avr-mem.sh)
hadcon-projects.7z7z hadcon-projects.7z manage 19 MB 2011-07-13 - 17:46 PeterZumbruch tar ball of all hadcon related projects, to be merged
hadcon-projects_4.3.7z7z hadcon-projects_4.3.7z manage 17 MB 2011-11-14 - 18:02 PeterZumbruch tar ball of all hadcon related projects, 4.3 actual release
Topic revision: r39 - 2020-12-11, PeterZumbruch - This page was cached on 2021-01-18 - 12:25.

This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding GSI Wiki? Send feedback | Imprint (german) | Privacy Policy (german)