jimy-byerley / etherage

An ethercat master library written in pure rust, the closest possible to the ethercat nature
https://docs.rs/etherage
12 stars 1 forks source link

add utilities for PDO mappings #4

Closed jimy-byerley closed 1 year ago

jimy-byerley commented 1 year ago

We need utilities to generate and apply PDO mappings

Here is how it should work for the user:

// establish mapping, it only concerns one group
let mapping = Mapping::new()
    let slave = mapping.push(42)
        let syncmanager = slave.enable(Input)
            let pdo = syncmanager.push(Pdo{index: 0x1600, entries: 3})
                let position = pdo.push(Sdo::<i32>::complete(0x1234))
                let status = pdo.push(Sdo::<StatusWord>::subitem(0x1234, 1))
                pdo.finish()
            let range = syncmanager.finish()
            ...
            let offset = slave.map(range)
                let position = offset.mapped(position)
                let status = offset.mapped(status)
        let syncmanager = slave.push(Input)
            let pdo = syncmanager.push(Pdo{index: 0x1600, entries: 10})
                let position = pdo.push(Sdo::<i32>::complete(0x1234))
                let status = pdo.push(Sdo::<StatusWord>::subitem(0x1234, 1))
                pdo.finish()
            syncmanager.finish()
    let group = mapping.finish(None)

// at any moment, to configure the user desired slaves
let slave = slave.switch::<PreOperational>()
mapping.apply(slave)  // this applies the part of the mapping that concerns the given slave
let slave = slave.switch::<SafeOperational>()
let slave = slave.expect::<Operational>()

// use groups to exchange process data
group.exchange()
let data = group.data()
status.get(data)
position.set(data, 4345)

This API is using

The previous code sample shows a mapping for several slaves, starting at logical address 0 To allow several such mappings to be used independently, a MappingAllocator shall be used. It is only a concept from this library and not from ethercat, allocating a portion of the logical memory to each mapping

// for several groups, and hot-plug, use an allocator
let allocator = MappingAllocator::new()
let mapping1 = Mapping::new()
    ...
let group1 = mapping1.finish(Some(&allocator))  // reserve a logical memory area for this mapping

let mapping2 = Mapping::new()
        ...
let group2 = mapping.finish(Some(&allocator))

// in case of hot-disconnect of a group and we want to reuse its allocated memory
drop(group1)
let mapping3 = Mapping::new()
        ...
let group3 = mapping.finish(Some(&allocator))  // this might reuse the memoryused by group1
jimy-byerley commented 1 year ago

Here it is, since merging of this branch, we now have etherage::mapping with such tools, even slightly more flexible than expected !