Lab exercise code for FAE Summit 09/2019.

Revision:
58:cf54c181a632
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/neo_iso_drv.cpp	Wed Sep 18 17:40:11 2019 +0000
@@ -0,0 +1,138 @@
+/*
+ * 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;
+}
+
+}