NM500 / NeuroShield

Dependents:   NeuroShield_SimpleScript NeuroShield_andIMU NeuroShield_Gesture_Recognition

NeuroShieldSPI.cpp

Committer:
nepes_ai
Date:
2020-02-11
Revision:
3:6163399b611e
Parent:
2:2812bcbcaaea

File content as of revision 3:6163399b611e:

/*
 * NeuroShield.cpp - Driver for NeuroShield
 * Copyright (c) 2016, General Vision Inc, All rights reserved
 * Copyright (c) 2017, nepes inc, All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

/*
 * Revision History (v1.1.5)
 * 2020/02/04    v1.1.5    Add dummy for switching between sd-card and nm spi
 * 2018/06/22    v1.1.4    Minor changes
 * 2018/01/03    v1.1.3    Add burst-mode read
 * 2017/12/20    v1.1.2    Modify the structure of neurondata
 * 2017/12/11    v1.1.1    Add Powersave command and Minor changes to the library
 * 2017/08/17    v1.0.0    First Release
 */

#include "mbed.h"
#include <NeuroShield.h>
#include <NeuroShieldSPI.h>

SPI device(SPI_MOSI, SPI_MISO, SPI_SCK);    // PA_7, PA_6, PA_5
DigitalOut nm500_ss(D7);                    // NM500_SSn

// ------------------------------------------------------------ //
//    Constructor to the class ShieldSPI
// ------------------------------------------------------------ 
NeuroShieldSPI::NeuroShieldSPI(){ 
}

// ------------------------------------------------------------ 
// Initialize the SPI communication and verify proper interface
// to the NM500 by reading the default Minif value of 2-bytes
// return an error=0 otherwise=1
// ------------------------------------------------------------ 
bool NeuroShieldSPI::connect()
{
    uint16_t read_value;
    
    // for shield board test
    nm500_ss = HIGH;
    
    //
    device.format(8,0);
    device.frequency(2000000);  // 2MHz
    
    // return 1 if NM500 present and SPI comm successful
    for (int i = 0; i < 10; i++) {
        reset();    // NM500 reset
        wait_ms(100);
        write(NM_FORGET, 0);
        wait_ms(50);
        read_value = read(NM_MINIF);
        if (read_value == 2)
            return(1);
        wait_ms(50);
    }
    
    return(0);
}

// --------------------------------------------------------
// SPI Read the register of a given module (module + reg = addr)
//---------------------------------------------------------
uint16_t NeuroShieldSPI::read(uint8_t reg)
{
    //device.lock();
    
    device.write(0xff);                     // dummy for switching between sd-card and nm spi
    
    nm500_ss = LOW;
    device.write(1);                        // Dummy for ID
    device.write((uint8_t)module_nm500);
    device.write(0);
    device.write(0);
    device.write(reg);
    device.write(0);
    device.write(0);
    device.write(1);                        // expect 1 word back
    uint16_t data = device.write(0);        // Send 0 to push upper data out
    data = (data << 8) + device.write(0);   // Send 0 to push lower data out
    nm500_ss = HIGH;
    
    //device.unlock();
    
    return(data);
}

void NeuroShieldSPI::readVector16(uint16_t* data, uint16_t size)
{
    //device.lock();
    
    device.write(0xff);                                 // dummy for switching between sd-card and nm spi
    
    nm500_ss = LOW;
    device.write(1);
    device.write((uint8_t)module_nm500);
    device.write(0);
    device.write(0);
    device.write(NM_COMP);
    device.write(0);
    device.write((uint8_t)((size >> 8) & 0x00FF));
    device.write((uint8_t)(size & 0x00FF));
    for (int i = 0; i < size; i++) {
        *data = device.write(0);
        *data = (*data << 8) + device.write(0);
        data++;
    }
    nm500_ss = HIGH;
    
    //device.unlock();
}

// ---------------------------------------------------------
// SPI Write the register of a given module (module + reg = addr)
// ---------------------------------------------------------
void NeuroShieldSPI::write(uint8_t reg, uint16_t data)
{
    //device.lock();
    
    device.write(0xff);                                 // dummy for switching between sd-card and nm spi
    
    nm500_ss = LOW;
    device.write(1);                                    // Dummy for ID
    device.write((uint8_t)(module_nm500 + 0x80));       // module and write flag
    device.write(0);
    device.write(0);
    device.write(reg);
    device.write(0);
    device.write(0);
    device.write(1);                                    // expect 1 word back
    if ((reg == NM_COMP) || (reg == NM_LCOMP)) {
        device.write(0x00);                             // upper data
        device.write((uint8_t)(data & 0x00FF));         // lower data
    }
    else {
        device.write((uint8_t)((data >> 8) & 0x00FF));  // upper data
        device.write((uint8_t)(data & 0x00FF));         // lower data
    }
    nm500_ss = HIGH;
    
    //device.unlock();
}

// ----------------------------------------------------------------
// SPI Write burst mode at COMP register
// ----------------------------------------------------------------
uint16_t NeuroShieldSPI::writeVector(uint8_t* data, uint16_t size)
{
    if (size > NEURON_SIZE)                         // to use SR-mode
        return(0);
    
    //device.lock();
    
    device.write(0xff);                             // dummy for switching between sd-card and nm spi
    
    nm500_ss = LOW;
    device.write(1);                                // Dummy for ID
    device.write((uint8_t)(module_nm500 + 0x80));   // module and write flag
    device.write(0);
    device.write(0);
    device.write(NM_COMP);
    device.write(0);
    device.write((uint8_t)((size >> 8) & 0x00FF));
    device.write((uint8_t)(size & 0x00FF));         // 1 ~ 256 byte
    for (int i = 0; i < size; i++) {
        device.write(0x00);                         // COMP' upper data = 0x00
        device.write((uint8_t)(*data));             // lower data
        data++;
    }
    nm500_ss = HIGH;
    
    //device.unlock();
    
    return(size);
}

uint16_t NeuroShieldSPI::writeVector16(uint16_t* data, uint16_t size)
{
    if (size > NEURON_SIZE)                         // to use SR-mode
        return(0);
    
    //device.lock();
    
    device.write(0xff);                             // dummy for switching between sd-card and nm spi
    
    nm500_ss = LOW;
    device.write(1);                                // Dummy for ID
    device.write((uint8_t)(module_nm500 + 0x80));   // module and write flag
    device.write(0);
    device.write(0);
    device.write(NM_COMP);
    device.write(0);
    device.write((uint8_t)((size >> 8) & 0x00FF));
    device.write((uint8_t)(size & 0x00FF));         // 1 ~ 256 byte
    for (int i = 0; i < size; i++) {
        device.write(0x00);                         // COMP' upper data = 0x00
        device.write((uint8_t)((*data) & 0x00FF));  // lower data
        data++;
    }
    nm500_ss = HIGH;
    
    //device.unlock();
    
    return(size);
}

// ----------------------------------------------------------------
// read FPGA Version
// ----------------------------------------------------------------
uint16_t NeuroShieldSPI::version()
{
    //device.lock();
    
    device.write(0xff);                     // dummy for switching between sd-card and nm spi
    
    nm500_ss = LOW;
    device.write(1);                        // Dummy for ID
    device.write((uint8_t)module_fpga);     // address (4-byte)
    device.write(0);
    device.write(0);
    device.write(1);                        // version check : 0x01
    device.write(0);                        // word size (3-byte)
    device.write(0);
    device.write(1);
    uint16_t data = device.write(0);        // Send 0 to push upper data out
    data = (data << 8) + device.write(0);   // Send 0 to push lower data out
    nm500_ss = HIGH;
    
    //device.unlock();
    
    return(data);
}

// ----------------------------------------------------------------
// excute NM500 SW reset
// ----------------------------------------------------------------
void NeuroShieldSPI::reset()
{
    //device.lock();
    
    device.write(0xff);                             // dummy for switching between sd-card and nm spi
    
    nm500_ss = LOW;
    device.write(1);                                // Dummy for ID
    device.write((uint8_t)(module_fpga + 0x80));    // address (4-byte)
    device.write(0);
    device.write(0);
    device.write(2);                                // nm500 sw reset : 0x02
    device.write(0);                                // word size (3-byte)
    device.write(0);
    device.write(1);                                // expect 1 word back
    device.write(0);
    device.write(0);
    nm500_ss = HIGH;
    
    //device.unlock();
}

// ----------------------------------------------------------------
// LED scenario select
// ----------------------------------------------------------------
void NeuroShieldSPI::ledSelect(uint8_t data)
{
    //device.lock();
    
    device.write(0xff);                             // dummy for switching between sd-card and nm spi
    
    nm500_ss = LOW;
    device.write(1);                                // Dummy for ID
    device.write((uint8_t)(module_led + 0x80));     // address (4-byte)
    device.write(0);
    device.write(0);
    device.write(data);                             // led scenario select
    device.write(0);                                // word size (3-byte)
    device.write(0);
    device.write(1);                                // expect 1 word back
    device.write(0);
    device.write(0);
    nm500_ss = HIGH;
    
    //deviece.unlock();
}