development checking

pull/1/head
Steve Lascos 7 years ago
parent 442f871e01
commit b86c583fb5
  1. 161
      src/BASpiMemory.cpp
  2. 69
      src/BASpiMemory.h
  3. 142
      src/BATypes.h
  4. 251
      src/LibBasicFunctions.h

@ -36,6 +36,7 @@ constexpr int SPI_MISO_MEM1 = 5;
constexpr int SPI_SCK_MEM1 = 20; constexpr int SPI_SCK_MEM1 = 20;
// SPI Constants // SPI Constants
constexpr int SPI_WRITE_MODE_REG = 0x1;
constexpr int SPI_WRITE_CMD = 0x2; constexpr int SPI_WRITE_CMD = 0x2;
constexpr int SPI_READ_CMD = 0x3; constexpr int SPI_READ_CMD = 0x3;
constexpr int SPI_ADDR_2_MASK = 0xFF0000; constexpr int SPI_ADDR_2_MASK = 0xFF0000;
@ -128,6 +129,7 @@ void BASpiMemory::write(size_t address, uint8_t *data, size_t numBytes)
digitalWrite(m_csPin, HIGH); digitalWrite(m_csPin, HIGH);
} }
void BASpiMemory::zero(size_t address, size_t numBytes) void BASpiMemory::zero(size_t address, size_t numBytes)
{ {
m_spi->beginTransaction(m_settings); m_spi->beginTransaction(m_settings);
@ -257,4 +259,163 @@ void BASpiMemory::read16(size_t address, uint16_t *dest, size_t numWords)
digitalWrite(m_csPin, HIGH); digitalWrite(m_csPin, HIGH);
} }
/////////////////////////////////////////////////////////////////////////////
// BASpiMemoryDMA
/////////////////////////////////////////////////////////////////////////////
BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes)
: BASpiMemory(memDeviceId), m_bufferSize(bufferSizeBytes)
{
int cs;
switch (memDeviceId) {
case SpiDeviceId::SPI_DEVICE0 :
cs = SPI_CS_MEM0;
break;
case SpiDeviceId::SPI_DEVICE1 :
cs = SPI_CS_MEM1;
break;
default :
cs = SPI_CS_MEM0;
}
m_cs = new ActiveLowChipSelect(cs, m_settings);
// add 4 bytes to buffer for SPI CMD and 3 bytes of addresse
m_txBuffer = new uint8_t[bufferSizeBytes+4];
m_rxBuffer = new uint8_t[bufferSizeBytes+4];
}
BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes)
: BASpiMemory(memDeviceId, speedHz), m_bufferSize(bufferSizeBytes)
{
int cs;
switch (memDeviceId) {
case SpiDeviceId::SPI_DEVICE0 :
cs = SPI_CS_MEM0;
break;
case SpiDeviceId::SPI_DEVICE1 :
cs = SPI_CS_MEM1;
break;
}
m_cs = new ActiveLowChipSelect(cs, m_settings);
m_txBuffer = new uint8_t[bufferSizeBytes+4];
m_rxBuffer = new uint8_t[bufferSizeBytes+4];
}
BASpiMemoryDMA::~BASpiMemoryDMA()
{
delete m_cs;
if (m_txBuffer) delete [] m_txBuffer;
if (m_rxBuffer) delete [] m_rxBuffer;
}
void BASpiMemoryDMA::m_setSpiCmdAddr(int command, size_t address, uint8_t *dest)
{
dest[0] = command;
dest[1] = ((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT);
dest[2] = ((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT);
dest[3] = ((address & SPI_ADDR_0_MASK));
}
void BASpiMemoryDMA::begin(void)
{
switch (m_memDeviceId) {
case SpiDeviceId::SPI_DEVICE0 :
m_csPin = SPI_CS_MEM0;
m_spi = &SPI;
m_spi->setMOSI(SPI_MOSI_MEM0);
m_spi->setMISO(SPI_MISO_MEM0);
m_spi->setSCK(SPI_SCK_MEM0);
m_spi->begin();
m_spiDma = &DMASPI0;
break;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case SpiDeviceId::SPI_DEVICE1 :
m_csPin = SPI_CS_MEM1;
m_spi = &SPI1;
m_spi->setMOSI(SPI_MOSI_MEM1);
m_spi->setMISO(SPI_MISO_MEM1);
m_spi->setSCK(SPI_SCK_MEM1);
m_spi->begin();
m_spiDma = &DMASPI1;
break;
#endif
default :
// unreachable since memDeviceId is an enumerated class
return;
}
m_spiDma->begin();
m_spiDma->start();
m_started = true;
}
// SPI must build up a payload that starts the teh CMD/Address first. It will cycle
// through the payloads in a circular buffer and use the transfer objects to check if they
// are done before continuing.
void BASpiMemoryDMA::write(size_t address, uint8_t *data, size_t numBytes)
{
while ( m_txTransfer->busy()) {}
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memcpy(m_txBuffer+4, data, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer);
}
void BASpiMemoryDMA::zero(size_t address, size_t numBytes)
{
while ( m_txTransfer->busy()) {}
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
*m_txTransfer = DmaSpi::Transfer(nullptr, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer);
}
void BASpiMemoryDMA::write16(size_t address, uint16_t *data, size_t numWords)
{
while ( m_txTransfer->busy()) {}
size_t numBytes = sizeof(uint16_t)*numWords;
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memcpy(m_txBuffer+4, data, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer);
}
void BASpiMemoryDMA::zero16(size_t address, size_t numWords)
{
while ( m_txTransfer->busy()) {}
size_t numBytes = sizeof(uint16_t)*numWords;
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memset(m_txBuffer+4, 0, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer);
}
void BASpiMemoryDMA::read(size_t address, uint8_t *data, size_t numBytes)
{
while ( m_rxTransfer->busy()) {}
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer);
*m_rxTransfer = DmaSpi::Transfer(nullptr, transferCount, m_rxBuffer, 0, m_cs);
m_spiDma->registerTransfer(*m_rxTransfer);
}
void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords)
{
while ( m_rxTransfer->busy()) {}
m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer);
size_t numBytes = sizeof(uint16_t)*numWords;
uint16_t transferCount = numBytes + 4;
*m_rxTransfer = DmaSpi::Transfer(nullptr, transferCount, m_rxBuffer, 0, m_cs);
m_spiDma->registerTransfer(*m_rxTransfer);
}
void BASpiMemoryDMA::readBufferContents(size_t bufferOffset, uint8_t *dest, size_t numBytes)
{
memcpy(dest, m_rxBuffer+4, numBytes);
}
} /* namespace BAGuitar */ } /* namespace BAGuitar */

@ -23,7 +23,9 @@
#define __SRC_BASPIMEMORY_H #define __SRC_BASPIMEMORY_H
#include <SPI.h> #include <SPI.h>
#include <DmaSpi.h>
#include "BATypes.h"
#include "BAHardware.h" #include "BAHardware.h"
namespace BAGuitar { namespace BAGuitar {
@ -47,25 +49,25 @@ public:
BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz); BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz);
virtual ~BASpiMemory(); virtual ~BASpiMemory();
void begin(void); virtual void begin();
/// write a single data word to the specified address /// write a single data word to the specified address
/// @param address the address in the SPI RAM to write to /// @param address the address in the SPI RAM to write to
/// @param data the value to write /// @param data the value to write
void write(size_t address, uint8_t data); void write(size_t address, uint8_t data);
void write(size_t address, uint8_t *data, size_t numBytes); virtual void write(size_t address, uint8_t *data, size_t numBytes);
void zero(size_t address, size_t numBytes); virtual void zero(size_t address, size_t numBytes);
void write16(size_t address, uint16_t data); void write16(size_t address, uint16_t data);
void write16(size_t address, uint16_t *data, size_t numWords); virtual void write16(size_t address, uint16_t *data, size_t numWords);
void zero16(size_t address, size_t numWords); virtual void zero16(size_t address, size_t numWords);
/// read a single 8-bit data word from the specified address /// read a single 8-bit data word from the specified address
/// @param address the address in the SPI RAM to read from /// @param address the address in the SPI RAM to read from
/// @return the data that was read /// @return the data that was read
uint8_t read(size_t address); uint8_t read(size_t address);
void read(size_t address, uint8_t *data, size_t numBytes); virtual void read(size_t address, uint8_t *data, size_t numBytes);
/// read a single 16-bit data word from the specified address /// read a single 16-bit data word from the specified address
/// @param address the address in the SPI RAM to read from /// @param address the address in the SPI RAM to read from
@ -76,11 +78,11 @@ public:
/// @param address the address in the SPI RAM to read from /// @param address the address in the SPI RAM to read from
/// @param dest the pointer to the destination /// @param dest the pointer to the destination
/// @param numWords the number of 16-bit words to transfer /// @param numWords the number of 16-bit words to transfer
void read16(size_t address, uint16_t *dest, size_t numWords); virtual void read16(size_t address, uint16_t *dest, size_t numWords);
bool isStarted() const { return m_started; } bool isStarted() const { return m_started; }
private: protected:
SPIClass *m_spi = nullptr; SPIClass *m_spi = nullptr;
SpiDeviceId m_memDeviceId; // the MEM device being control with this instance SpiDeviceId m_memDeviceId; // the MEM device being control with this instance
uint8_t m_csPin; // the IO pin number for the CS on the controlled SPI device uint8_t m_csPin; // the IO pin number for the CS on the controlled SPI device
@ -89,7 +91,56 @@ private:
}; };
class BASpiMemoryException {}; //constexpr int MAX_DMA_XFERS = 4;
class BASpiMemoryDMA : public BASpiMemory {
BASpiMemoryDMA() = delete;
/// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2).
/// @details default is 20 Mhz
/// @param memDeviceId specify which MEM to control with SpiDeviceId.
/// @param bufferSize size of buffer to store DMA transfers
BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes);
/// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2)
/// @param memDeviceId specify which MEM to control with SpiDeviceId.
/// @param speedHz specify the desired speed in Hz.
/// @param bufferSize size of buffer to store DMA transfers
BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes);
virtual ~BASpiMemoryDMA();
void write(size_t address, uint8_t *data, size_t numBytes) override;
void zero(size_t address, size_t numBytes) override;
void write16(size_t address, uint16_t *data, size_t numWords) override;
void zero16(size_t address, size_t numWords) override;
/// read a single 8-bit data word from the specified address
/// @param address the address in the SPI RAM to read from
/// @return the data that was read
void read(size_t address, uint8_t *data, size_t numBytes) override;
/// read a block 16-bit data word from the specified address
/// @param address the address in the SPI RAM to read from
/// @param dest the pointer to the destination
/// @param numWords the number of 16-bit words to transfer
void read16(size_t address, uint16_t *dest, size_t numWords) override;
void begin() override;
void readBufferContents(size_t bufferOffset, uint8_t *dest, size_t numBytes);
private:
AbstractDmaSpi<DmaSpi0, SPIClass, SPI> *m_spiDma = nullptr;
ActiveLowChipSelect *m_cs = nullptr;
size_t m_bufferSize;
uint8_t *m_txBuffer = nullptr;
DmaSpi::Transfer *m_txTransfer;
uint8_t *m_rxBuffer = nullptr;
DmaSpi::Transfer *m_rxTransfer;
void m_setSpiCmdAddr(int command, size_t address, uint8_t *dest);
// RingBuffer<DmaSpi::Transfer> m_txFifo(MAX_DMA_XFERS);
// RingBuffer<DmaSpi::Transfer> m_rxFifo(MAX_DMA_XFERS);
};
} /* namespace BAGuitar */ } /* namespace BAGuitar */

@ -0,0 +1,142 @@
/*
* BATypes.h
*
* Created on: Feb 7, 2018
* Author: slascos
*/
#ifndef SRC_BATYPES_H_
#define SRC_BATYPES_H_
namespace BAGuitar {
/**************************************************************************//**
* Customer RingBuffer with random access
*****************************************************************************/
template <class T>
class RingBuffer {
public:
RingBuffer() = delete;
/// Construct a RingBuffer of specified max size
/// @param maxSize number of entries in ring buffer
RingBuffer(const size_t maxSize) : m_maxSize(maxSize) {
m_buffer = new T[maxSize]();
}
virtual ~RingBuffer(){
if (m_buffer) delete [] m_buffer;
}
/// Add an element to the back of the queue
/// @param element element to add to queue
/// returns 0 if success, otherwise error
int push_back(T element) {
//Serial.println(String("RingBuffer::push_back...") + m_head + String(":") + m_tail + String(":") + m_size);
if ( (m_head == m_tail) && (m_size > 0) ) {
// overflow
Serial.println("RingBuffer::push_back: overflow");
return -1;
}
m_buffer[m_head] = element;
if (m_head < (m_maxSize-1) ) {
m_head++;
} else {
m_head = 0;
}
m_size++;
return 0;
}
/// Remove the element at teh front of the queue
/// @returns 0 if success, otherwise error
int pop_front() {
if (m_size == 0) {
// buffer is empty
//Serial.println("RingBuffer::pop_front: buffer is empty\n");
return -1;
}
if (m_tail < m_maxSize-1) {
m_tail++;
} else {
m_tail = 0;
}
m_size--;
//Serial.println(String("RingBuffer::pop_front: ") + m_head + String(":") + m_tail + String(":") + m_size);
return 0;
}
/// Get the element at the front of the queue
/// @returns element at front of queue
T front() const {
return m_buffer[m_tail];
}
/// get the element at the back of the queue
/// @returns element at the back of the queue
T back() const {
return m_buffer[m_head-1];
}
/// Get a previously pushed elememt
/// @param offset zero is last pushed, 1 is second last, etc.
/// @returns the absolute index corresponding to the requested offset.
size_t get_index_from_back(size_t offset = 0) const {
// the target at m_head - 1 - offset or m_maxSize + m_head -1 - offset;
size_t idx = (m_maxSize + m_head -1 - offset);
if ( idx >= m_maxSize) {
idx -= m_maxSize;
}
return idx;
}
/// get the current size of the queue
/// @returns size of the queue
size_t size() const {
return m_size;
}
/// get the maximum size the queue can hold
/// @returns maximum size of the queue
size_t max_size() const {
return m_maxSize;
}
/// get the element at the specified absolute index
/// @param index element to retrieve from absolute queue position
/// @returns the request element
T& operator[] (size_t index) {
return m_buffer[index];
}
/// get the element at the specified absolute index
/// @param index element to retrieve from absolute queue position
/// @returns the request element
T at(size_t index) const {
return m_buffer[index];
}
/// DEBUG: Prints the status of the Ringbuffer. NOte using this much printing will usually cause audio glitches
void print() const {
for (int idx=0; idx<m_maxSize; idx++) {
Serial.print(idx + String(" address: ")); Serial.print((uint32_t)m_buffer[idx], HEX);
Serial.print(" data: "); Serial.println((uint32_t)m_buffer[idx]->data, HEX);
}
}
private:
size_t m_head=0; ///< back of the queue
size_t m_tail=0; ///< front of the queue
size_t m_size=0; ///< current size of the qeueu
T *m_buffer = nullptr; ///< pointer to the allocated buffer array
const size_t m_maxSize; ///< maximum size of the queue
};
} // BAGuitar
#endif /* SRC_BATYPES_H_ */

@ -27,6 +27,7 @@
#include "Arduino.h" #include "Arduino.h"
#include "Audio.h" #include "Audio.h"
#include "BATypes.h"
#include "LibMemoryManagement.h" #include "LibMemoryManagement.h"
#ifndef __LIBBASICFUNCTIONS_H #ifndef __LIBBASICFUNCTIONS_H
@ -213,131 +214,131 @@ private:
}; };
/**************************************************************************//** ///**************************************************************************//**
* Customer RingBuffer with random access // * Customer RingBuffer with random access
*****************************************************************************/ // *****************************************************************************/
template <class T> //template <class T>
class RingBuffer { //class RingBuffer {
public: //public:
RingBuffer() = delete; // RingBuffer() = delete;
//
/// Construct a RingBuffer of specified max size // /// Construct a RingBuffer of specified max size
/// @param maxSize number of entries in ring buffer // /// @param maxSize number of entries in ring buffer
RingBuffer(const size_t maxSize) : m_maxSize(maxSize) { // RingBuffer(const size_t maxSize) : m_maxSize(maxSize) {
m_buffer = new T[maxSize](); // m_buffer = new T[maxSize]();
} // }
virtual ~RingBuffer(){ // virtual ~RingBuffer(){
if (m_buffer) delete [] m_buffer; // if (m_buffer) delete [] m_buffer;
} // }
//
/// Add an element to the back of the queue // /// Add an element to the back of the queue
/// @param element element to add to queue // /// @param element element to add to queue
/// returns 0 if success, otherwise error // /// returns 0 if success, otherwise error
int push_back(T element) { // int push_back(T element) {
//
//Serial.println(String("RingBuffer::push_back...") + m_head + String(":") + m_tail + String(":") + m_size); // //Serial.println(String("RingBuffer::push_back...") + m_head + String(":") + m_tail + String(":") + m_size);
if ( (m_head == m_tail) && (m_size > 0) ) { // if ( (m_head == m_tail) && (m_size > 0) ) {
// overflow // // overflow
Serial.println("RingBuffer::push_back: overflow"); // Serial.println("RingBuffer::push_back: overflow");
return -1; // return -1;
} // }
//
m_buffer[m_head] = element; // m_buffer[m_head] = element;
if (m_head < (m_maxSize-1) ) { // if (m_head < (m_maxSize-1) ) {
m_head++; // m_head++;
} else { // } else {
m_head = 0; // m_head = 0;
} // }
m_size++; // m_size++;
//
return 0; // return 0;
} // }
//
/// Remove the element at teh front of the queue // /// Remove the element at teh front of the queue
/// @returns 0 if success, otherwise error // /// @returns 0 if success, otherwise error
int pop_front() { // int pop_front() {
//
if (m_size == 0) { // if (m_size == 0) {
// buffer is empty // // buffer is empty
//Serial.println("RingBuffer::pop_front: buffer is empty\n"); // //Serial.println("RingBuffer::pop_front: buffer is empty\n");
return -1; // return -1;
} // }
if (m_tail < m_maxSize-1) { // if (m_tail < m_maxSize-1) {
m_tail++; // m_tail++;
} else { // } else {
m_tail = 0; // m_tail = 0;
} // }
m_size--; // m_size--;
//Serial.println(String("RingBuffer::pop_front: ") + m_head + String(":") + m_tail + String(":") + m_size); // //Serial.println(String("RingBuffer::pop_front: ") + m_head + String(":") + m_tail + String(":") + m_size);
return 0; // return 0;
} // }
//
/// Get the element at the front of the queue // /// Get the element at the front of the queue
/// @returns element at front of queue // /// @returns element at front of queue
T front() const { // T front() const {
return m_buffer[m_tail]; // return m_buffer[m_tail];
} // }
//
/// get the element at the back of the queue // /// get the element at the back of the queue
/// @returns element at the back of the queue // /// @returns element at the back of the queue
T back() const { // T back() const {
return m_buffer[m_head-1]; // return m_buffer[m_head-1];
} // }
//
/// Get a previously pushed elememt // /// Get a previously pushed elememt
/// @param offset zero is last pushed, 1 is second last, etc. // /// @param offset zero is last pushed, 1 is second last, etc.
/// @returns the absolute index corresponding to the requested offset. // /// @returns the absolute index corresponding to the requested offset.
size_t get_index_from_back(size_t offset = 0) const { // size_t get_index_from_back(size_t offset = 0) const {
// the target at m_head - 1 - offset or m_maxSize + m_head -1 - offset; // // the target at m_head - 1 - offset or m_maxSize + m_head -1 - offset;
size_t idx = (m_maxSize + m_head -1 - offset); // size_t idx = (m_maxSize + m_head -1 - offset);
//
if ( idx >= m_maxSize) { // if ( idx >= m_maxSize) {
idx -= m_maxSize; // idx -= m_maxSize;
} // }
//
return idx; // return idx;
} // }
//
/// get the current size of the queue // /// get the current size of the queue
/// @returns size of the queue // /// @returns size of the queue
size_t size() const { // size_t size() const {
return m_size; // return m_size;
} // }
//
/// get the maximum size the queue can hold // /// get the maximum size the queue can hold
/// @returns maximum size of the queue // /// @returns maximum size of the queue
size_t max_size() const { // size_t max_size() const {
return m_maxSize; // return m_maxSize;
} // }
//
/// get the element at the specified absolute index // /// get the element at the specified absolute index
/// @param index element to retrieve from absolute queue position // /// @param index element to retrieve from absolute queue position
/// @returns the request element // /// @returns the request element
T& operator[] (size_t index) { // T& operator[] (size_t index) {
return m_buffer[index]; // return m_buffer[index];
} // }
//
/// get the element at the specified absolute index // /// get the element at the specified absolute index
/// @param index element to retrieve from absolute queue position // /// @param index element to retrieve from absolute queue position
/// @returns the request element // /// @returns the request element
T at(size_t index) const { // T at(size_t index) const {
return m_buffer[index]; // return m_buffer[index];
} // }
//
/// DEBUG: Prints the status of the Ringbuffer. NOte using this much printing will usually cause audio glitches // /// DEBUG: Prints the status of the Ringbuffer. NOte using this much printing will usually cause audio glitches
void print() const { // void print() const {
for (int idx=0; idx<m_maxSize; idx++) { // for (int idx=0; idx<m_maxSize; idx++) {
Serial.print(idx + String(" address: ")); Serial.print((uint32_t)m_buffer[idx], HEX); // Serial.print(idx + String(" address: ")); Serial.print((uint32_t)m_buffer[idx], HEX);
Serial.print(" data: "); Serial.println((uint32_t)m_buffer[idx]->data, HEX); // Serial.print(" data: "); Serial.println((uint32_t)m_buffer[idx]->data, HEX);
} // }
} // }
private: //private:
size_t m_head=0; ///< back of the queue // size_t m_head=0; ///< back of the queue
size_t m_tail=0; ///< front of the queue // size_t m_tail=0; ///< front of the queue
size_t m_size=0; ///< current size of the qeueu // size_t m_size=0; ///< current size of the qeueu
T *m_buffer = nullptr; ///< pointer to the allocated buffer array // T *m_buffer = nullptr; ///< pointer to the allocated buffer array
const size_t m_maxSize; ///< maximum size of the queue // const size_t m_maxSize; ///< maximum size of the queue
}; //};
} }

Loading…
Cancel
Save