Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: NeuroShield_SimpleScript NeuroShield_andIMU NeuroShield_Gesture_Recognition
Diff: NeuroShield.cpp
- Revision:
- 1:0c6bf23f2fc8
- Parent:
- 0:529602524696
- Child:
- 2:2812bcbcaaea
--- a/NeuroShield.cpp Thu Aug 17 23:31:15 2017 +0000 +++ b/NeuroShield.cpp Thu Jan 25 02:20:37 2018 +0000 @@ -31,6 +31,14 @@ * */ +/* + * Revision History (v1.1.3) + * 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> @@ -57,9 +65,15 @@ else { countTotalNeurons(); clearNeurons(); + + uint16_t fpga_version = spi.version(); + if ((fpga_version != 0x0001) && (fpga_version != 0x0002)) + support_burst_read = 1; + else + support_burst_read = 0; + + return(total_neurons); } - - return(total_neurons); } // -------------------------------------------------------- @@ -68,11 +82,14 @@ void NeuroShield::setNcr(uint16_t value) { spi.write(NM_NCR, value); + POWERSAVE; } uint16_t NeuroShield::getNcr() { - return(spi.read(NM_NCR)); + uint16_t ret_val = spi.read(NM_NCR); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -81,11 +98,14 @@ void NeuroShield::setComp(uint8_t value) { spi.write(NM_COMP, (value & 0x00FF)); + POWERSAVE; } uint8_t NeuroShield::getComp() { - return((uint8_t)(spi.read(NM_COMP) & 0x00FF)); + uint8_t ret_val = (uint8_t)(spi.read(NM_COMP) & 0x00FF); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -94,6 +114,7 @@ void NeuroShield::setLastComp(uint8_t value) { spi.write(NM_LCOMP, (value & 0x00FF)); + POWERSAVE; } // -------------------------------------------------------- @@ -102,6 +123,7 @@ void NeuroShield::setIndexComp(uint16_t value) { spi.write(NM_INDEXCOMP, value); + POWERSAVE; } // -------------------------------------------------------- @@ -109,7 +131,9 @@ //--------------------------------------------------------- uint16_t NeuroShield::getDist() { - return(spi.read(NM_DIST)); + uint16_t ret_val = spi.read(NM_DIST); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -118,11 +142,14 @@ void NeuroShield::setCat(uint16_t value) { spi.write(NM_CAT, value); + POWERSAVE; } uint16_t NeuroShield::getCat() { - return(spi.read(NM_CAT)); + uint16_t ret_val = spi.read(NM_CAT); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -131,11 +158,14 @@ void NeuroShield::setAif(uint16_t value) { spi.write(NM_AIF, value); + POWERSAVE; } uint16_t NeuroShield::getAif() { - return(spi.read(NM_AIF)); + uint16_t ret_val = spi.read(NM_AIF); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -144,11 +174,14 @@ void NeuroShield::setMinif(uint16_t value) { spi.write(NM_MINIF, value); + POWERSAVE; } uint16_t NeuroShield::getMinif() { - return(spi.read(NM_MINIF)); + uint16_t ret_val = spi.read(NM_MINIF); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -157,11 +190,14 @@ void NeuroShield::setMaxif(uint16_t value) { spi.write(NM_MAXIF, value); + POWERSAVE; } uint16_t NeuroShield::getMaxif() { - return(spi.read(NM_MAXIF)); + uint16_t ret_val = spi.read(NM_MAXIF); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -169,7 +205,9 @@ //--------------------------------------------------------- uint16_t NeuroShield::getNid() { - return(spi.read(NM_NID)); + uint16_t ret_val = spi.read(NM_NID); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -181,11 +219,14 @@ // GCR[7]= Norm (0 for L1; 1 for LSup) // GCR[6-0]= Active context value spi.write(NM_GCR, value); + POWERSAVE; } uint16_t NeuroShield::getGcr() { - return(spi.read(NM_GCR)); + uint16_t ret_val = spi.read(NM_GCR); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -194,6 +235,7 @@ void NeuroShield::resetChain() { spi.write(NM_RSTCHAIN, 0); + POWERSAVE; } // -------------------------------------------------------- @@ -206,11 +248,14 @@ void NeuroShield::setNsr(uint16_t value) { spi.write(NM_NSR, value); + POWERSAVE; } uint16_t NeuroShield::getNsr() { - return(spi.read(NM_NSR)); + uint16_t ret_val = spi.read(NM_NSR); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -218,7 +263,9 @@ //--------------------------------------------------------- uint16_t NeuroShield::getNcount() { - return(spi.read(NM_NCOUNT)); + uint16_t ret_val = spi.read(NM_NCOUNT); + POWERSAVE; + return(ret_val); } // -------------------------------------------------------- @@ -227,6 +274,7 @@ void NeuroShield::setPowerSave() { spi.write(NM_POWERSAVE, 1); + POWERSAVE; } // ------------------------------------------------------------ @@ -236,6 +284,7 @@ void NeuroShield::forget() { spi.write(NM_FORGET, 0); + POWERSAVE; } // ------------------------------------------------------------ @@ -246,6 +295,7 @@ { spi.write(NM_FORGET, 0); spi.write(NM_MAXIF, maxif); + POWERSAVE; } // ------------------------------------------------------------ @@ -269,6 +319,7 @@ } spi.write(NM_NSR, 0x0000); spi.write(NM_FORGET, 0); + POWERSAVE; } // -------------------------------------------------------------- @@ -280,10 +331,14 @@ { spi.write(NM_FORGET, 0); spi.write(NM_NSR, 0x0010); - for (int i = 0; i < NEURON_SIZE; i++) + spi.write(NM_TESTCAT, 1); + spi.write(NM_NSR, 0x0000); + for (int i = 0; i < NEURON_SIZE; i++) { + spi.write(NM_INDEXCOMP, i); spi.write(NM_TESTCOMP, 0); - spi.write(NM_RSTCHAIN, 0); - spi.write(NM_NSR, 0x0000); + } + spi.write(NM_FORGET, 0); + POWERSAVE; } // -------------------------------------------------------- @@ -292,10 +347,12 @@ //--------------------------------------------------------- uint16_t NeuroShield::broadcast(uint8_t vector[], uint16_t length) { - spi.writeVector(NM_COMP, vector, (length - 1)); + uint16_t ret_val; + spi.writeVector(vector, (length - 1)); spi.write(NM_LCOMP, vector[length - 1]); - - return(spi.read(NM_NSR)); + ret_val = spi.read(NM_NSR); + POWERSAVE; + return(ret_val); } //----------------------------------------------- @@ -303,9 +360,12 @@ //---------------------------------------------- uint16_t NeuroShield::learn(uint8_t vector[], uint16_t length, uint16_t category) { + uint16_t ret_val; broadcast(vector, length); spi.write(NM_CAT, category); - return(spi.read(NM_NCOUNT)); + ret_val = spi.read(NM_NCOUNT); + POWERSAVE; + return(ret_val); } // --------------------------------------------------------- @@ -316,8 +376,11 @@ // --------------------------------------------------------- uint16_t NeuroShield::classify(uint8_t vector[], uint16_t length) { + uint16_t ret_val; broadcast(vector, length); - return(spi.read(NM_NSR)); + ret_val = spi.read(NM_NSR); + POWERSAVE; + return(ret_val); } //---------------------------------------------- @@ -326,11 +389,14 @@ //---------------------------------------------- uint16_t NeuroShield::classify(uint8_t vector[], uint16_t length, uint16_t* distance, uint16_t* category, uint16_t* nid) { + uint16_t ret_val; broadcast(vector, length); *distance = spi.read(NM_DIST); *category = spi.read(NM_CAT); *nid = spi.read(NM_NID); - return(spi.read(NM_NSR)); + ret_val = spi.read(NM_NSR); + POWERSAVE; + return(ret_val); } //---------------------------------------------- @@ -356,6 +422,7 @@ nid[i] = spi.read(NM_NID); } } + POWERSAVE; return(recog_nbr); } @@ -370,6 +437,7 @@ uint16_t read_val = spi.read(NM_GCR); read_val = (read_val & 0xFF80) | (context & 0x007F); spi.write(NM_GCR, read_val); + POWERSAVE; } // ------------------------------------------------------------ @@ -385,6 +453,7 @@ spi.write(NM_GCR, read_val); spi.write(NM_MINIF, minif); spi.write(NM_MAXIF, maxif); + POWERSAVE; } // ------------------------------------------------------------ @@ -398,6 +467,7 @@ *context = (uint8_t)(spi.read(NM_GCR) & 0x007F); *minif = spi.read(NM_MINIF); *maxif = spi.read(NM_MAXIF); + POWERSAVE; } // -------------------------------------------------------- @@ -407,6 +477,7 @@ { uint16_t temp_nsr = spi.read(NM_NSR); spi.write(NM_NSR, (temp_nsr & 0x00DF)); + POWERSAVE; } // -------------------------------------------------------- @@ -416,161 +487,188 @@ { uint16_t temp_nsr = spi.read(NM_NSR); spi.write(NM_NSR, (temp_nsr | 0x0020)); + POWERSAVE; } //------------------------------------------------------------- // Read the contents of the neuron pointed by index in the chain of neurons -// starting at index 0 +// starting at index 1 //------------------------------------------------------------- -void NeuroShield::readNeuron(uint16_t nid, uint8_t model[], uint16_t* ncr, uint16_t* aif, uint16_t* cat) +void NeuroShield::readNeuron(uint16_t nid, uint16_t model[], uint16_t* ncr, uint16_t* aif, uint16_t* cat) { + if (nid == 0) { + *ncr = 0xFFFF; + *aif = 0xFFFF; + *cat = 0xFFFF; + return; + } + uint16_t temp_nsr = spi.read(NM_NSR); spi.write(NM_NSR, 0x0010); spi.write(NM_RSTCHAIN, 0); - if (nid > 0) { + if (nid > 1) { // move to index in the chain of neurons - for (int i = 0; i < nid; i++) + for (int i = 1; i < nid; i++) spi.read(NM_CAT); } *ncr = spi.read(NM_NCR); - for (int i = 0; i < NEURON_SIZE; i++) - model[i] = spi.read(NM_COMP); + if (support_burst_read == 1) { + spi.readVector16(model, NEURON_SIZE); + } + else { + for (int i = 0; i < NEURON_SIZE; i++) + model[i] = spi.read(NM_COMP); + } *aif = spi.read(NM_AIF); *cat = spi.read(NM_CAT); - spi.write(NM_NSR, temp_nsr); // set the NN back to its calling status + spi.write(NM_NSR, temp_nsr); // set the NN back to its calling status + POWERSAVE; } //------------------------------------------------------------- // Read the contents of the neuron pointed by index in the chain of neurons -// starting index is 0 -// Returns an array of NEURONSIZE bytes with the following format -// 2-bytes NCR, NEURONSIZE-bytes COMP, 2-bytes AIF, 2-bytes MINIF, 2-bytes CAT +// starting index is 1 +// Returns an array of (NEURON_SIZE + 4) words with the following format +// NCR, NEURON_SIZE * COMP, AIF, MINIF, CAT //------------------------------------------------------------- -void NeuroShield::readNeuron(uint16_t nid, uint8_t neuron[]) +void NeuroShield::readNeuron(uint16_t nid, uint16_t neuron[]) { + if (nid == 0) { + for (int i = 0; i < (NEURON_SIZE + 4); i++) { + neuron[i] = 0xFFFF; + } + return; + } + uint16_t temp_nsr = spi.read(NM_NSR); spi.write(NM_NSR, 0x0010); spi.write(NM_RSTCHAIN, 0); - if (nid > 0) { + if (nid > 1) { // move to index in the chain of neurons - for (int i = 0; i < nid; i++) + for (int i = 1; i < nid; i++) spi.read(NM_CAT); } - uint16_t read_val = spi.read(NM_NCR); - neuron[0] = (uint8_t)((read_val >> 8) & 0x00FF); - neuron[1] = (uint8_t)(read_val & 0x00FF); - for (int i = 0; i < NEURON_SIZE; i++) - neuron[i + 2] = spi.read(NM_COMP); - read_val = spi.read(NM_AIF); - neuron[NEURON_SIZE + 2] = (uint8_t)((read_val >> 8) & 0x00FF); - neuron[NEURON_SIZE + 3] = (uint8_t)(read_val & 0x00FF); - read_val = spi.read(NM_MINIF); - neuron[NEURON_SIZE + 4] = (uint8_t)((read_val >> 8) & 0x00FF); - neuron[NEURON_SIZE + 5] = (uint8_t)(read_val & 0x00FF); - read_val = spi.read(NM_CAT); - neuron[NEURON_SIZE + 6] = (uint8_t)((read_val >> 8) & 0x00FF); - neuron[NEURON_SIZE + 7] = (uint8_t)(read_val & 0x00FF); - spi.write(NM_NSR, temp_nsr); // set the NN back to its calling status + + neuron[0] = spi.read(NM_NCR); + if (support_burst_read == 1) { + spi.readVector16(&neuron[1], NEURON_SIZE); + } + else { + for (int i = 0; i < NEURON_SIZE; i++) + neuron[i + 1] = spi.read(NM_COMP); + } + neuron[NEURON_SIZE + 1] = spi.read(NM_AIF); + neuron[NEURON_SIZE + 2] = spi.read(NM_MINIF); + neuron[NEURON_SIZE + 3] = spi.read(NM_CAT); + spi.write(NM_NSR, temp_nsr); // set the NN back to its calling status + POWERSAVE; } //---------------------------------------------------------------------------- -// Read the contents of the committed neurons and output in a generic format compatible with -// all NeuroMem chips regardless of their neuron size and capacity -// The neurons array should be sized to HEADERSIZE + MAXNEURON * (NEURONSIZE + 8) -// Default header size of 8 bytes: headerSize, reserved, 2-bytes MaxLength, 4-bytes neuronCount -// followed by neuroCount record of (MaxLength + 8) bytes: -// 2-bytes NCR, MaxLength-bytes COMP, 2-bytes AIF, 2-bytes MINIF, 2-bytes CAT +// Read the contents of the committed neurons +// The output array has a dimension ncount * neurondata +// neurondata describes the content of a neuron and has a dimension (NEURON_SIZE + 4) words +// and with the following format NCR, NEURON_SIZE * COMP, AIF, MINIF, CAT //---------------------------------------------------------------------------- -uint16_t NeuroShield::readNeurons(uint8_t neurons[]) +uint16_t NeuroShield::readNeurons(uint16_t neurons[]) { - uint32_t offset = 8; - + uint32_t offset = 0; uint16_t ncount = spi.read(NM_NCOUNT); - uint16_t temp_nsr = spi.read(NM_NSR); // save value to restore NN status upon exit + uint16_t temp_nsr = spi.read(NM_NSR); // save value to restore NN status upon exit spi.write(NM_NSR, 0x0010); spi.write(NM_RSTCHAIN, 0); - neurons[0] = offset; // default header size of 8 bytes - neurons[1] = 0; // reserved to encode a future format identifier - neurons[2] = 0x01; - neurons[3] = 0x00; - neurons[4] = 0; - neurons[5] = 0; - neurons[6] = ((ncount >> 8) & 0x00FF); - neurons[7] = (ncount & 0x00FF); for (int i = 0; i < ncount; i++) { - uint16_t read_val = spi.read(NM_NCR); - neurons[offset] = (uint8_t)((read_val >> 8) & 0x00FF); - neurons[offset + 1] = (uint8_t)(read_val & 0x00FF); - for (int j = 0; j < NEURON_SIZE; j++) { - read_val = spi.read(NM_COMP); - neurons[offset + 2 + j] = (uint8_t)(read_val & 0x00FF); + neurons[offset + 0] = spi.read(NM_NCR); + if (support_burst_read == 1) { + spi.readVector16(&neurons[offset + 1], NEURON_SIZE); } - read_val = spi.read(NM_AIF); - neurons[offset + NEURON_SIZE + 2] = (uint8_t)((read_val >> 8) & 0x00FF); - neurons[offset + NEURON_SIZE + 3] = (uint8_t)(read_val & 0x00FF); - read_val = spi.read(NM_MINIF); - neurons[offset + NEURON_SIZE + 4] = (uint8_t)((read_val >> 8) & 0x00FF); - neurons[offset + NEURON_SIZE + 5] = (uint8_t)(read_val & 0x00FF); - read_val = spi.read(NM_CAT); - neurons[offset + NEURON_SIZE + 6] = (uint8_t)((read_val >> 8) & 0x00FF); - neurons[offset + NEURON_SIZE + 7] = (uint8_t)(read_val & 0x00FF); - offset += (NEURON_SIZE + 8); + else { + for (int j = 0; j < NEURON_SIZE; j++) { + neurons[offset + 1 + j] = spi.read(NM_COMP); + } + } + neurons[offset + 1 + NEURON_SIZE] = spi.read(NM_AIF); + neurons[offset + 2 + NEURON_SIZE] = spi.read(NM_MINIF); + neurons[offset + 3 + NEURON_SIZE] = spi.read(NM_CAT); + offset += (NEURON_SIZE + 4); } - spi.write(NM_NSR, temp_nsr); // set the NN back to its calling status + spi.write(NM_NSR, temp_nsr); // set the NN back to its calling status + POWERSAVE; return(ncount); } +void NeuroShield::readCompVector(uint16_t* data, uint16_t size) +{ + if (support_burst_read == 1) { + spi.readVector16(data, size); + } + else { + for (int i = 0; i < size; i++) { + *data = spi.read(NM_COMP); + data++; + } + } +} + //--------------------------------------------------------------------- -// Clear the committed neurons and restore a new content for the neurons -// from an input array formatted as follows -// Default header size of 8 bytes: headerSize, reserved, 2-bytes MaxLength, 4-bytes neuronCount -// followed by neuroCount record of (MaxLength + 8) bytes: -// 2-bytes NCR, MaxLength-bytes COMP, 2-bytes AIF, 2-bytes MINIF, 2-bytes CAT +// Clear the neurons and write their content from an input array +// The input array has a dimension ncount * neurondata +// neurondata describes the content of a neuron and has a dimension (NEURON_SIZE + 4) words +// and with the following format NCR, NEURON_SIZE * COMP, AIF, MINIF, CAT //--------------------------------------------------------------------- -uint16_t NeuroShield::writeNeurons(uint8_t neurons[]) +void NeuroShield::writeNeurons(uint16_t neurons[], uint16_t ncount) { - uint32_t offset = neurons[0]; - uint16_t ncount = (neurons[6] << 8) + neurons[7]; + uint32_t offset = 0; if (ncount > total_neurons) ncount = total_neurons; - uint16_t temp_nsr = spi.read(NM_NSR); // save value to restore NN status upon exit + uint16_t temp_nsr = spi.read(NM_NSR); // save value to restore NN status upon exit uint16_t temp_gcr = spi.read(NM_GCR); - spi.write(NM_FORGET, 0); + clearNeurons(); spi.write(NM_NSR, 0x0010); spi.write(NM_RSTCHAIN, 0); for (int i = 0; i < ncount; i++) { - spi.write(NM_NCR, neurons[offset + 1]); - for (int j = 0; j < NEURON_SIZE; j++) - spi.write(NM_COMP, neurons[offset + 2 + j]); - spi.write(NM_AIF, (neurons[offset + NEURON_SIZE + 2] << 8) + neurons[offset + NEURON_SIZE + 3]); - spi.write(NM_MINIF, (neurons[offset + NEURON_SIZE + 4] << 8) + neurons[offset + NEURON_SIZE + 5]); - spi.write(NM_CAT, (neurons[offset + NEURON_SIZE + 6] << 8) + neurons[offset + NEURON_SIZE + 7]); - offset += (NEURON_SIZE + 8); + spi.write(NM_NCR, neurons[offset + 0]); + spi.writeVector16(&neurons[offset + 1], NEURON_SIZE); + spi.write(NM_AIF, neurons[offset + 1 + NEURON_SIZE]); + spi.write(NM_MINIF, neurons[offset + 2 + NEURON_SIZE]); + spi.write(NM_CAT, neurons[offset + 3 + NEURON_SIZE]); + offset += (NEURON_SIZE + 4); } - spi.write(NM_NSR, temp_nsr); // set the NN back to its calling status + spi.write(NM_NSR, temp_nsr); // set the NN back to its calling status spi.write(NM_GCR, temp_gcr); - return(spi.read(NM_NCOUNT)); + POWERSAVE; } // -------------------------------------------------------- -// just for TEST, must be modified +// Write N-component +//--------------------------------------------------------- +void NeuroShield::writeCompVector(uint16_t* data, uint16_t size) +{ + spi.writeVector16(data, size); +} + +// -------------------------------------------------------- +// Get/Set the NM500 register value //--------------------------------------------------------- uint16_t NeuroShield::testCommand(uint8_t read_write, uint8_t reg, uint16_t data) { + uint16_t ret_val = 0; if (read_write == 0) { - return(spi.read(reg)); + ret_val = spi.read(reg); } else if (read_write == 1) { spi.write(reg, data); - return(0); } - - return(0); + POWERSAVE; + return(ret_val); } // ---------------------------------------------------------------- // Get FPGA Version +// [15:8] board type : 00 = NeuroShield, 01 = Prodigy ... +// [ 7:4] board version +// [ 3:0] fpga version // ---------------------------------------------------------------- uint16_t NeuroShield::fpgaVersion() { @@ -591,28 +689,4 @@ void NeuroShield::ledSelect(uint8_t data) { spi.ledSelect(data); -} - -// ---------------------------------------------------------------- -// Display committed neurons information -// ---------------------------------------------------------------- -void NeuroShield::displayNeurons(uint16_t length) -{ - // display the neurons - uint16_t ncount = spi.read(NM_NCOUNT); - printf("\n Committed neurons = %u", ncount); - - spi.write(NM_NSR, 0x0010); - spi.write(NM_RSTCHAIN, 0); - - for (int i = 0; i < ncount; i++) { - printf("\n NeuronID = %u \tComponents=", (i + 1)); - for (int j = 0; j < length; j++) { - printf("%u, " , spi.read(NM_COMP)); - } - printf("\tAIF = %u, ", spi.read(NM_AIF)); - printf("\tCAT = %u, ", spi.read(NM_CAT)); - } - - spi.write(NM_NSR, 0x0000); } \ No newline at end of file