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;
// SPI Constants
constexpr int SPI_WRITE_MODE_REG = 0x1;
constexpr int SPI_WRITE_CMD = 0x2;
constexpr int SPI_READ_CMD = 0x3;
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);
}
void BASpiMemory::zero(size_t address, size_t numBytes)
{
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);
}
/////////////////////////////////////////////////////////////////////////////
// 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 */

@ -23,7 +23,9 @@
#define __SRC_BASPIMEMORY_H
#include <SPI.h>
#include <DmaSpi.h>
#include "BATypes.h"
#include "BAHardware.h"
namespace BAGuitar {
@ -47,25 +49,25 @@ public:
BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz);
virtual ~BASpiMemory();
void begin(void);
virtual void begin();
/// write a single data word to the specified address
/// @param address the address in the SPI RAM to write to
/// @param data the value to write
void write(size_t address, uint8_t data);
void write(size_t address, uint8_t *data, size_t numBytes);
void zero(size_t address, size_t numBytes);
virtual void write(size_t address, uint8_t *data, 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, 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
/// @param address the address in the SPI RAM to read from
/// @return the data that was read
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
/// @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 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);
virtual void read16(size_t address, uint16_t *dest, size_t numWords);
bool isStarted() const { return m_started; }
private:
protected:
SPIClass *m_spi = nullptr;
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
@ -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 */

@ -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 "Audio.h"
#include "BATypes.h"
#include "LibMemoryManagement.h"
#ifndef __LIBBASICFUNCTIONS_H
@ -213,131 +214,131 @@ private:
};
/**************************************************************************//**
* 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
};
///**************************************************************************//**
// * 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
//};
}

Loading…
Cancel
Save