device-driver-codegen 2.1.0

Internal compiler crate for the device-driver toolkit
Documentation
{% decl block_generics %}
{% if block.root %}
    {% let block_generics = "<I>" %}
{% else %}
    {% let block_generics = "<'i, I>" %}
{% endif %}

{{ self::description_to_docstring(block.description) }}
{{ self::maybe_doc_alias(block.name, Case::Pascal) }}
#[derive(Debug)]
pub struct {{ block.name.to_case(Case::Pascal) }}{{block_generics}} {
    {% if block.root %}
    interface: I,
    {% else %}
    #[doc(hidden)]
    interface: &'i mut I,
    {% endif %}
    #[doc(hidden)]
    #[allow(unused)]
    base_address: {{device.internal_address_type}},
}

impl{{block_generics}} {{ block.name.to_case(Case::Pascal) }}{{block_generics}} {
    {% if block.root %}
    /// Create a new instance of the device
    pub const fn new(interface: I) -> Self {
        Self { interface, base_address: {{ device.address_offset }} }
    }

    /// Drop the driver instance and reclaim the interface
    pub fn free(self) -> I {
        self.interface
    }
    {% else %}
    /// Create a new instance of the block based on device interface
    #[doc(hidden)]
    fn new(interface: &'i mut I, base_address: {{device.internal_address_type}}) -> Self {
        Self { interface, base_address: base_address }
    }
    {% endif %}

    {% for method in block.methods %}
        {{ self::description_to_docstring(method.description) }}
        {{ self.get_block_method_docs(method) }}
        {{ self::maybe_doc_alias(method.name, Case::Snake) }}
        pub fn {{ method.name.to_case(Case::Snake) }}(
            &mut self,
            {% if let BlockMethodType::Block { .. } = method.method_type %}
            {% match method.repeat %}
                {% when Repeat::None %}
                {% when Repeat::Count { .. } %} index: usize
                {% when Repeat::Enum { enum_name, .. } %} index: {{enum_name.to_case(Case::Pascal)}}
            {% endmatch %}
            {% endif %}
        ) -> 
        {% match method.method_type %}
            {% when BlockMethodType::Block { name } %} {{name.to_case(Case::Pascal)}}<'_, I>
            {% when BlockMethodType::Register { field_set_name, access, .. } %}
            ::device_driver::RegisterOperation<
                '_,
                Self,
                {{field_set_name.to_case(Case::Pascal)}},
                {{block.register_address_type}},
                ::device_driver::{{access}},
                {% match method.repeat %}
                    {% when Repeat::None %} ()
                    {% when Repeat::Count { count, stride } %} ::device_driver::ArrayRepeat<{{count}}, {{stride}}>
                    {% when Repeat::Enum { enum_name, stride, .. } %} ::device_driver::EnumRepeat<{{enum_name.to_case(Case::Pascal)}}, {{stride}}>
                {% endmatch %}
            > where I: ::device_driver::RegisterInterfaceBase<AddressType = {{block.register_address_type}}>
            {% when BlockMethodType::Command { field_set_name_in, field_set_name_out } %}
            ::device_driver::CommandOperation<
                '_,
                Self,
                {{block.command_address_type}},
                {{self::get_command_fieldset_name(field_set_name_in)}},
                {{self::get_command_fieldset_name(field_set_name_out)}},
                {% match method.repeat %}
                    {% when Repeat::None %} ()
                    {% when Repeat::Count { count, stride } %} ::device_driver::ArrayRepeat<{{count}}, {{stride}}>
                    {% when Repeat::Enum { enum_name, stride, .. } %} ::device_driver::EnumRepeat<{{enum_name.to_case(Case::Pascal)}}, {{stride}}>
                {% endmatch %}
            > where I: ::device_driver::CommandInterfaceBase<AddressType = {{block.command_address_type}}>
            {% when BlockMethodType::Buffer { access } %}
            ::device_driver::BufferOperation<
                '_,
                Self,
                {{block.buffer_address_type}},
                ::device_driver::{{access}}
            > where I: ::device_driver::BufferInterfaceBase<AddressType = {{block.buffer_address_type}}>
        {% endmatch %}
        {
            {% if let BlockMethodType::Block { .. } = method.method_type %}
            {% match method.repeat %}
                {% when Repeat::None %} let address = self.base_address + {{method.address}};
                {% when Repeat::Count { count, stride } %}
                    let address = {
                        assert!(index < {{count}});
                        self.base_address + {{method.address}} + index as {{device.internal_address_type}} * {{stride}}
                    };
                {% when Repeat::Enum { enum_name, stride, .. } %}
                    let address = self.base_address + {{method.address}} + {{self::get_enum_base_type(driver, &enum_name)}}::from(index) as {{device.internal_address_type}} * {{stride}};
            {% endmatch %}
            {% else %}
                let address = self.base_address + {{method.address}};
            {% endif %}

            {% match method.method_type %}
                {% when BlockMethodType::Block { name } %}
                    {{name.to_case(Case::Pascal)}}::<'_, I>::new(::device_driver::Block::interface(self), address)
                {% endwhen %}
                {% when BlockMethodType::Register { field_set_name, access, reset_value } %}
                    ::device_driver::RegisterOperation::new(
                        self,
                        address as {{block.register_address_type}},
                        {% if let Some(rv) = reset_value %}
                            || {{field_set_name.to_case(Case::Pascal)}}::from([{{rv.value | join(", ")}}]),
                        {% else %}
                            {{field_set_name.to_case(Case::Pascal)}}::default,
                        {% endif %}
                    )
                {% endwhen %}
                {% when BlockMethodType::Command { field_set_name_in, field_set_name_out } %}
                    ::device_driver::CommandOperation::new(self, address as {{block.command_address_type}})
                {% endwhen %}
                {% when BlockMethodType::Buffer { access } %}
                    ::device_driver::BufferOperation::new(self, address as {{block.buffer_address_type}})
                {% endwhen %}
            {% endmatch %}
        }
    {% endfor %}
}

impl{{block_generics}} ::device_driver::Block for {{ block.name.to_case(Case::Pascal) }}{{block_generics}} {
    type Interface = I;
    type RegisterAddressType = {{ block.register_address_type }};
    type CommandAddressType = {{ block.command_address_type }};
    type BufferAddressType = {{ block.buffer_address_type }};
    type RegisterAddressMode = {{self::get_address_mode_const_value(block.register_address_mode)}};

    {% if block.root %}
    fn interface(&mut self) -> &mut Self::Interface {
        &mut self.interface
    }
    {% else %}
    fn interface(&mut self) -> &mut Self::Interface {
        self.interface
    }
    {% endif %}
}