Lab exercise code for FAE Summit 09/2019.

neo_iso_drv.cpp

Committer:
lru
Date:
2019-09-18
Revision:
59:4628ef4b0d52
Parent:
58:cf54c181a632

File content as of revision 59:4628ef4b0d52:

/*
 * Mbed OS device driver for Semtech TS13401 Neo-Iso SSR driver.
 *
 * Copyright (c) 2019 Future Electronics
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "neo_iso_drv.h"

namespace neoiso {

NeoIso::NeoIso( PinName clk_pin, PinName data_pin, uint8_t address) :
    _spi(clk_pin, data_pin, NC),
    _address(address),
    _on(0),
    _buffer_index(0)
{
    MBED_ASSERT(address < 8);
    // Round frequency up a bit:
    // To emulate CLK of 1MHz we need actual SPI clock of 2MHz.
    // However, on Sequana default i/o frequency is 50MHz, and SPI peripheral
    // needs actual clock 4x of its output. This gives nearest SPI frequency
    //  available from main clock of (50MHz/4)/6 = 2083kHz.
    // If we would request exactly 2MHz, the driver would set up the divider
    // as 7 (to not have clock faster that required) resulting in SPI clock
    // of 1.79MHz
    _spi.frequency(2100000);
    _spi.format(16, 0);
}

NeoIso::~NeoIso()
{
}

int NeoIso::send_command(page_t page, command_t command)
{
    // Clear buffer, this also embeds RESET/START command into the buffer.
    _clear_buffer();

    // Insert PAGE bits.
    uint8_t mask = 0x04;
    for(int i = 0 ; i < 3 ; ++i) {
        _buffer_put_bit(page & mask);
        mask >>= 1;
    }
    // Insert ADDRESS bits.
    mask = 0x04;
    for(int i = 0 ; i < 3 ; ++i) {
        _buffer_put_bit(_address & mask);
        mask >>= 1;
    }
    // Insert COMMAND bits.
    mask = 0x08;
    for(int i = 0 ; i < 4 ; ++i) {
        _buffer_put_bit(command & mask);
        mask >>= 1;
    }

    // Insert dummy '1' bits for status read out.
    for(int i = 0 ; i < 10 ; ++i) {
        _buffer_put_bit(1);
    }

    return _send_buffer();
}

int NeoIso::get_status(uint8_t &status)
{
    if (send_command(PAGE_COMMAND, COMMAND_POOL_STATE) == 0)
    {
        uint8_t temp = 0;
        int s_idx = RESET_LENGTH + 3 + 3 + 4 + 1;
        for (int i = s_idx; i < s_idx + 8; ++i) {
            temp <<= 1;
            temp |= (_rx_buffer[i] & 0x0f00) > 0;
        }
        status = temp;
        return 0;
    }
    return (-1);
}

int NeoIso::set_output(bool on)
{
    int status;

    if (on) {
         status = send_command(PAGE_COMMAND, COMMAND_ON_IMMEDIATE_WITH_DITHERING);
    } else {
         status = send_command(PAGE_COMMAND, COMMAND_OFF_IMMEDIATE);
    }

    if (status == 0) {
        _on = on;
    }
    return status;
}


void NeoIso::_clear_buffer()
{
    size_t i = 0;
    for (i = 0; i < RESET_LENGTH; ++i) {
        _tx_buffer[i] = BIT_RESET;
    }
    for (; i < MAX_COMMAND_LENGTH; ++i) {
        _tx_buffer[i] = BIT_ONE;
    }
    _buffer_index = RESET_LENGTH;
}

void NeoIso::_buffer_put_bit(bool bit)
{
    MBED_ASSERT(_buffer_index < MAX_COMMAND_LENGTH);

    _tx_buffer[_buffer_index++] = bit ? BIT_ONE : BIT_ZERO;
}

int NeoIso::_send_buffer()
{
    if (_spi.write((char*)_tx_buffer, 2*_buffer_index, (char*)_rx_buffer, 2*_buffer_index) != (int)(2*_buffer_index)) {
        return (-1);
    }
    return 0;
}

}