// © RiceMotion ( Robert Carl Rice ) 2012-2016 - All rights reserved


// This software makes use of tools and libraries obtained from open source projects or released for

// use by relevant hardware manufactures. However, this software is NOT a part of any open source project.

// It is released only on a "need to know" basis for beta testers of the "RiceCNC Interpolation Engine".

// Recipents of this source code must respect the confidential nature of this software and prevent any

// distribution that could result in counterfeit copies of the "RiceCNC Interpolation Engine".


// © RiceMotion ( Robert Carl Rice ) 2012-2016 - All rights reserved

#include     <SsiBuffer.h>

#include     <SsiDeviceQueue.h>



SsiBuffer::SsiBuffer( SsiDeviceQueue* aSsiDeviceQueue ) {

     ssiDeviceQueue     = aSsiDeviceQueue;


     nextSsiBuffer     = NULL;

     bytePointer          = NULL; };


SsiBuffer::~SsiBuffer() { // called automatically after derived destructor

     while( bytePointer ); };


uint32_t

     SsiBuffer::getWord() {

     

     return myData.dataWord; };


byte

     SsiBuffer::getByte() { // TxEOT interrupt except for first


     return bytePointer ?

          *bytePointer :

          0; }; // error


void

     SsiBuffer::receiveByte( byte receivedData ) { // TxEOT interrupt


     *bytePointer     = receivedData;

  

     if ( dataBytes ) {

          dataBytes--;

          bytePointer = &myData.dataByte[ dataBytes ]; }


     else {

          bytePointer          = NULL; // received last byte

          rxComplete();     // run callback function if one

          ssiDeviceQueue->dequeue(); }; };


void

     SsiBuffer::receiveWord( uint16_t receivedData ) {

     

     myData.dataWord = receivedData; // copy


     bytePointer          = NULL; // received last byte

     rxComplete();     // run callback function if one

     ssiDeviceQueue->dequeue(); };


void

     SsiBuffer::queueWithRegister( uint16_t aRegister ) {

     

     while ( isInQueue() ); // Block until prior command is processed


     myData.dataWord          = aRegister;

     bytePointer               = &command;

     queue(); };


void

     SsiBuffer::queueWith( uint8_t aCommand ) {

          

     queueWith( aCommand, 0, 0 ); };


void

     SsiBuffer::queueWith(

          uint8_t          aCommand,

          uint32_t     data,

          uint32_t     aMask ) {


     while ( isInQueue() ); // Block until prior command is processed


     command          = aCommand;

     myData.dataWord  = data > mask ?

          mask :

          data;

     mask             = aMask;

     bytePointer      = &command;

     if      ( mask == 0 )       dataBytes = 0;

//  else if ( mask & 0xFF000000 ) dataBytes = 4; // No dSpin data this long

     else if ( mask & 0xFF0000 ) dataBytes = 3;

     else if ( mask & 0xFFFF00 ) dataBytes = 2;

     else                        dataBytes = 1; // little-endian


     queue(); };


bool

     SsiBuffer::isInQueue() {


     IntMasterDisable();

          bool  queued = ( bytePointer != NULL );

     IntMasterEnable();


     return queued; };


void

     SsiBuffer::queue() {


     ssiDeviceQueue->queue( this ); };