You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							544 lines
						
					
					
						
							16 KiB
						
					
					
				
			
		
		
	
	
							544 lines
						
					
					
						
							16 KiB
						
					
					
				/*
 | 
						|
 * upstream_spi.c
 | 
						|
 *
 | 
						|
 *  Created on: 21/06/2015
 | 
						|
 *      Author: Robert Fisk
 | 
						|
 *
 | 
						|
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 | 
						|
 */
 | 
						|
 | 
						|
#include "upstream_interface_def.h"
 | 
						|
#include "upstream_spi.h"
 | 
						|
#include "stm32f4xx_hal.h"
 | 
						|
#include "board_config.h"
 | 
						|
#include "interrupts.h"
 | 
						|
 | 
						|
 | 
						|
 | 
						|
SPI_HandleTypeDef           Hspi1;
 | 
						|
UpstreamPacketTypeDef       UpstreamPacket0;
 | 
						|
UpstreamPacketTypeDef       UpstreamPacket1;
 | 
						|
UpstreamPacketTypeDef*      CurrentWorkingPacket;
 | 
						|
UpstreamPacketTypeDef*      NextTxPacket        = NULL;         //Indicates we have a pending TX packet
 | 
						|
 | 
						|
InterfaceStateTypeDef               UpstreamInterfaceState      = UPSTREAM_INTERFACE_IDLE;
 | 
						|
FreePacketCallbackTypeDef           PendingFreePacketCallback   = NULL; //Indicates someone is waiting for a packet buffer to become available
 | 
						|
SpiPacketReceivedCallbackTypeDef    ReceivePacketCallback       = NULL; //Indicates someone is waiting for a received packet
 | 
						|
 | 
						|
uint32_t                    TemporaryIncomingPacketLength;      //We don't actually care about what Downstream sends us when we are transmitting. We just need somewhere to put it so that our own packet length is not overwritten.
 | 
						|
uint8_t                     TxOkInterruptReceived = 0;
 | 
						|
uint8_t                     SentCommandClass;
 | 
						|
uint8_t                     SentCommand;
 | 
						|
 | 
						|
 | 
						|
void Upstream_BeginTransmitPacketSize(void);
 | 
						|
void Upstream_BeginTransmitPacketBody(void);
 | 
						|
HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void);
 | 
						|
void Upstream_BeginReceivePacketSize(UpstreamPacketTypeDef* freePacket);
 | 
						|
void Upstream_BeginReceivePacketBody(void);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void Upstream_InitSPI(void)
 | 
						|
{
 | 
						|
    UpstreamPacket0.Busy = NOT_BUSY;
 | 
						|
    UpstreamPacket1.Busy = NOT_BUSY;
 | 
						|
 | 
						|
    Hspi1.Instance = SPI1;
 | 
						|
    Hspi1.State = HAL_SPI_STATE_RESET;
 | 
						|
    Hspi1.Init.Mode = SPI_MODE_MASTER;
 | 
						|
    Hspi1.Init.Direction = SPI_DIRECTION_2LINES;
 | 
						|
    Hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
 | 
						|
    Hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
 | 
						|
    Hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
 | 
						|
    Hspi1.Init.NSS = SPI_NSS_SOFT;
 | 
						|
    Hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; //42MHz APB2 / 4 = 10.5Mbaud
 | 
						|
    Hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
 | 
						|
    Hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
 | 
						|
    Hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLED;
 | 
						|
    Hspi1.Init.CRCPolynomial = SPI_CRC_DEFAULTPOLYNOMIAL;
 | 
						|
    HAL_SPI_Init(&Hspi1);
 | 
						|
 | 
						|
    if (DOWNSTREAM_TX_OK_ACTIVE)
 | 
						|
    {
 | 
						|
        TxOkInterruptReceived = 1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//Used by USB interface classes, and by our internal RX code.
 | 
						|
HAL_StatusTypeDef Upstream_GetFreePacket(FreePacketCallbackTypeDef callback)
 | 
						|
{
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    //Do we already have a queued callback?
 | 
						|
    if (PendingFreePacketCallback != NULL)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    //Check if there is a free buffer now
 | 
						|
    if (UpstreamPacket0.Busy == NOT_BUSY)
 | 
						|
    {
 | 
						|
        UpstreamPacket0.Busy = BUSY;
 | 
						|
        callback(&UpstreamPacket0);
 | 
						|
        return HAL_OK;
 | 
						|
    }
 | 
						|
    if (UpstreamPacket1.Busy == NOT_BUSY)
 | 
						|
    {
 | 
						|
        UpstreamPacket1.Busy = BUSY;
 | 
						|
        callback(&UpstreamPacket1);
 | 
						|
        return HAL_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    //Otherwise save requested address for when a buffer becomes free in the future
 | 
						|
    PendingFreePacketCallback = callback;
 | 
						|
    return HAL_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
UpstreamPacketTypeDef* Upstream_GetFreePacketImmediately(void)
 | 
						|
{
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    //We are expecting a free buffer now
 | 
						|
    if (UpstreamPacket0.Busy == NOT_BUSY)
 | 
						|
    {
 | 
						|
        UpstreamPacket0.Busy = BUSY;
 | 
						|
        return &UpstreamPacket0;
 | 
						|
    }
 | 
						|
    if (UpstreamPacket1.Busy == NOT_BUSY)
 | 
						|
    {
 | 
						|
        UpstreamPacket1.Busy = BUSY;
 | 
						|
        return &UpstreamPacket1;
 | 
						|
    }
 | 
						|
 | 
						|
    //Should not happen:
 | 
						|
    UPSTREAM_SPI_FREAKOUT;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//Used by USB interface classes, and by our internal RX code.
 | 
						|
void Upstream_ReleasePacket(UpstreamPacketTypeDef* packetToRelease)
 | 
						|
{
 | 
						|
    FreePacketCallbackTypeDef tempCallback;
 | 
						|
    
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((packetToRelease != &UpstreamPacket0) &&
 | 
						|
        (packetToRelease != &UpstreamPacket1))
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (packetToRelease->Busy != BUSY)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (PendingFreePacketCallback != NULL)
 | 
						|
    {
 | 
						|
        tempCallback = PendingFreePacketCallback;   //In extreme situations, running this callback can trigger another request for a free packet,
 | 
						|
        PendingFreePacketCallback = NULL;           //thereby causing GetFreePacket to freak out. So we need to clear the callback indicator first.
 | 
						|
        tempCallback(packetToRelease);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        packetToRelease->Busy = NOT_BUSY;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//Used by USB interface classes only.
 | 
						|
//OK to call when still transmitting another packet.
 | 
						|
//Not OK to call when receiving or waiting for downstream reply,
 | 
						|
//as we can't let the size/packet sequence get out of sync.
 | 
						|
HAL_StatusTypeDef Upstream_TransmitPacket(UpstreamPacketTypeDef* packetToWrite)
 | 
						|
{
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
    
 | 
						|
    //Sanity checks
 | 
						|
    if ((packetToWrite != &UpstreamPacket0) &&
 | 
						|
        (packetToWrite != &UpstreamPacket1))
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
    if ((packetToWrite->Busy != BUSY) ||
 | 
						|
        (packetToWrite->Length16 < UPSTREAM_PACKET_LEN_MIN_16) ||
 | 
						|
        (packetToWrite->Length16 > UPSTREAM_PACKET_LEN_16))
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
    if (NextTxPacket != NULL)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (UpstreamInterfaceState)
 | 
						|
    {
 | 
						|
    case UPSTREAM_INTERFACE_TX_SIZE_WAIT:
 | 
						|
    case UPSTREAM_INTERFACE_TX_SIZE:
 | 
						|
    case UPSTREAM_INTERFACE_TX_PACKET_WAIT:
 | 
						|
    case UPSTREAM_INTERFACE_TX_PACKET:
 | 
						|
        NextTxPacket = packetToWrite;
 | 
						|
        break;
 | 
						|
 | 
						|
    case UPSTREAM_INTERFACE_IDLE:
 | 
						|
        UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE_WAIT;
 | 
						|
        CurrentWorkingPacket = packetToWrite;
 | 
						|
        SentCommandClass = CurrentWorkingPacket->CommandClass;
 | 
						|
        SentCommand = CurrentWorkingPacket->Command;
 | 
						|
 | 
						|
        //Downstream may have set TxOk pin before we wanted to transmit.
 | 
						|
        //In this case we can go ahead and transmit now.
 | 
						|
        if (TxOkInterruptReceived)
 | 
						|
        {
 | 
						|
            TxOkInterruptReceived = 0;
 | 
						|
            Upstream_BeginTransmitPacketSize();
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
    default:
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
    return HAL_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//Called at the end of the SPI TxRx transfer,
 | 
						|
//at SPI1 interrupt priority. Assume *hspi points to our hspi1.
 | 
						|
//We TxRx our outgoing packet because the SPI hardware freaks out if we only Tx it :-/
 | 
						|
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
 | 
						|
{
 | 
						|
    SpiPacketReceivedCallbackTypeDef tempPacketCallback;
 | 
						|
    UpstreamPacketTypeDef* tempPacketToFree;
 | 
						|
 | 
						|
    SPI1_NSS_DEASSERT;
 | 
						|
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    //Finished transmitting packet size
 | 
						|
    if (UpstreamInterfaceState == UPSTREAM_INTERFACE_TX_SIZE)
 | 
						|
    {
 | 
						|
        UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_PACKET_WAIT;
 | 
						|
        if (TxOkInterruptReceived)
 | 
						|
        {
 | 
						|
            TxOkInterruptReceived = 0;
 | 
						|
            Upstream_BeginTransmitPacketBody();
 | 
						|
        }
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    //Finished transmitting packet body
 | 
						|
    if (UpstreamInterfaceState == UPSTREAM_INTERFACE_TX_PACKET)
 | 
						|
    {
 | 
						|
        if ((PendingFreePacketCallback != NULL) && (NextTxPacket == NULL))
 | 
						|
        {
 | 
						|
            UPSTREAM_SPI_FREAKOUT;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        tempPacketToFree = CurrentWorkingPacket;
 | 
						|
 | 
						|
        if (NextTxPacket != NULL)
 | 
						|
        {
 | 
						|
            //NextTxPacket has already passed the checks in Upstream_TransmitPacket.
 | 
						|
            //So we just need to pass it to HAL_SPI_Transmit_DMA.
 | 
						|
            UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE_WAIT;
 | 
						|
            CurrentWorkingPacket = NextTxPacket;
 | 
						|
            NextTxPacket = NULL;
 | 
						|
            SentCommandClass = CurrentWorkingPacket->CommandClass;
 | 
						|
            SentCommand = CurrentWorkingPacket->Command;
 | 
						|
            if (TxOkInterruptReceived)
 | 
						|
            {
 | 
						|
                TxOkInterruptReceived = 0;
 | 
						|
                Upstream_BeginTransmitPacketSize();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            //No packet queued for transmission:
 | 
						|
            UpstreamInterfaceState = UPSTREAM_INTERFACE_IDLE;
 | 
						|
            if (ReceivePacketCallback != NULL)
 | 
						|
            {
 | 
						|
                Upstream_CheckBeginPacketReception();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        //Release old packet after moving Next to Current
 | 
						|
        Upstream_ReleasePacket(tempPacketToFree);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    
 | 
						|
 | 
						|
 | 
						|
    if (UpstreamInterfaceState == UPSTREAM_INTERFACE_RX_SIZE)
 | 
						|
    {
 | 
						|
        if ((CurrentWorkingPacket->Length16 < UPSTREAM_PACKET_LEN_MIN_16) ||
 | 
						|
            (CurrentWorkingPacket->Length16 > UPSTREAM_PACKET_LEN_16))
 | 
						|
        {
 | 
						|
            UPSTREAM_SPI_FREAKOUT;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_PACKET_WAIT;
 | 
						|
        if (TxOkInterruptReceived)
 | 
						|
        {
 | 
						|
            TxOkInterruptReceived = 0;
 | 
						|
            Upstream_BeginReceivePacketBody();
 | 
						|
        }
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (UpstreamInterfaceState == UPSTREAM_INTERFACE_RX_PACKET)
 | 
						|
    {
 | 
						|
        UpstreamInterfaceState = UPSTREAM_INTERFACE_IDLE;
 | 
						|
        if (ReceivePacketCallback == NULL)
 | 
						|
        {
 | 
						|
            UPSTREAM_SPI_FREAKOUT;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if ((CurrentWorkingPacket->CommandClass == COMMAND_CLASS_ERROR) &&
 | 
						|
            (CurrentWorkingPacket->Command == COMMAND_ERROR_DEVICE_DISCONNECTED))
 | 
						|
        {
 | 
						|
            Upstream_ReleasePacket(CurrentWorkingPacket);
 | 
						|
            ReceivePacketCallback = NULL;
 | 
						|
            Upstream_StateMachine_DeviceDisconnected();
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (((CurrentWorkingPacket->CommandClass & COMMAND_CLASS_MASK) != (SentCommandClass & COMMAND_CLASS_MASK)) ||
 | 
						|
            (CurrentWorkingPacket->Command != SentCommand))
 | 
						|
        {
 | 
						|
            UPSTREAM_SPI_FREAKOUT;
 | 
						|
            Upstream_ReleasePacket(CurrentWorkingPacket);
 | 
						|
            CurrentWorkingPacket = NULL;        //Call back with a NULL packet to indicate error
 | 
						|
        }
 | 
						|
 | 
						|
        //USB interface may want to receive another packet immediately,
 | 
						|
        //so clear ReceivePacketCallback before the call.
 | 
						|
        //It is the callback's responsibility to release the packet buffer we are passing to it!
 | 
						|
        tempPacketCallback = ReceivePacketCallback;
 | 
						|
        ReceivePacketCallback = NULL;
 | 
						|
        tempPacketCallback(CurrentWorkingPacket);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    //case default:
 | 
						|
    UPSTREAM_SPI_FREAKOUT;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//Used by USB interface classes.
 | 
						|
//Ok to call when idle or transmitting.
 | 
						|
//Not OK to call when receiving or waiting for downstream reply.
 | 
						|
HAL_StatusTypeDef Upstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callback)
 | 
						|
{
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (ReceivePacketCallback != NULL)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    ReceivePacketCallback = callback;
 | 
						|
    return Upstream_CheckBeginPacketReception();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//Internal use only.
 | 
						|
HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void)
 | 
						|
{
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_RX_SIZE_WAIT)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return HAL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    if (UpstreamInterfaceState == UPSTREAM_INTERFACE_IDLE)
 | 
						|
    {
 | 
						|
        UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_SIZE_WAIT;
 | 
						|
        if (TxOkInterruptReceived)
 | 
						|
        {
 | 
						|
            TxOkInterruptReceived = 0;
 | 
						|
            Upstream_GetFreePacket(Upstream_BeginReceivePacketSize);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return HAL_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//This is called by EXTI3 falling edge interrupt,
 | 
						|
//indicating that downstream is ready for the next transaction.
 | 
						|
void Upstream_TxOkInterrupt(void)
 | 
						|
{
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    
 | 
						|
    switch (UpstreamInterfaceState)
 | 
						|
    {
 | 
						|
    case UPSTREAM_INTERFACE_IDLE:
 | 
						|
        TxOkInterruptReceived = 1;
 | 
						|
        break;
 | 
						|
 | 
						|
    case UPSTREAM_INTERFACE_TX_SIZE_WAIT:
 | 
						|
        Upstream_BeginTransmitPacketSize();
 | 
						|
        break;
 | 
						|
 | 
						|
    case UPSTREAM_INTERFACE_TX_PACKET_WAIT:
 | 
						|
        Upstream_BeginTransmitPacketBody();
 | 
						|
        break;
 | 
						|
 | 
						|
    case UPSTREAM_INTERFACE_RX_SIZE_WAIT:
 | 
						|
        Upstream_GetFreePacket(Upstream_BeginReceivePacketSize);
 | 
						|
        break;
 | 
						|
 | 
						|
    case UPSTREAM_INTERFACE_RX_PACKET_WAIT:
 | 
						|
        Upstream_BeginReceivePacketBody();
 | 
						|
        break;
 | 
						|
 | 
						|
    default:
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Upstream_BeginTransmitPacketSize(void)
 | 
						|
{
 | 
						|
    UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE;
 | 
						|
    SPI1_NSS_ASSERT;
 | 
						|
    if (HAL_SPI_TransmitReceive(&Hspi1,
 | 
						|
                                    (uint8_t*)&CurrentWorkingPacket->Length16,
 | 
						|
                                    (uint8_t*)&TemporaryIncomingPacketLength,
 | 
						|
                                    2,                                  //We only need to write one word, but the peripheral library freaks out...
 | 
						|
                                    SPI_TIMEOUT_VALUE) != HAL_OK)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
    }
 | 
						|
 | 
						|
    HAL_SPI_TxRxCpltCallback(&Hspi1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Upstream_BeginTransmitPacketBody(void)
 | 
						|
{
 | 
						|
    UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_PACKET;
 | 
						|
    SPI1_NSS_ASSERT;
 | 
						|
 | 
						|
    if (HAL_SPI_TransmitReceive_DMA(&Hspi1,
 | 
						|
                                    &CurrentWorkingPacket->CommandClass,
 | 
						|
                                    &CurrentWorkingPacket->CommandClass,
 | 
						|
                                    ((CurrentWorkingPacket->Length16 < 2) ? 2 : CurrentWorkingPacket->Length16)) != HAL_OK)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//Internal use only.
 | 
						|
//Called when we want to receive downstream packet, and a packet buffer has become free.
 | 
						|
void Upstream_BeginReceivePacketSize(UpstreamPacketTypeDef* freePacket)
 | 
						|
{
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (UpstreamInterfaceState != UPSTREAM_INTERFACE_RX_SIZE_WAIT)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_SIZE;
 | 
						|
    CurrentWorkingPacket = freePacket;
 | 
						|
    CurrentWorkingPacket->Length16 = 0;     //Our RX buffer is used by HAL_SPI_TransmitReceive_DMA as dummy TX data, we set Length to 0 so downstream will know this is a dummy packet.
 | 
						|
    SPI1_NSS_ASSERT;
 | 
						|
    if (HAL_SPI_TransmitReceive(&Hspi1,
 | 
						|
                                    (uint8_t*)&CurrentWorkingPacket->Length16,
 | 
						|
                                    (uint8_t*)&CurrentWorkingPacket->Length16,
 | 
						|
                                    2,                                     //We only need to write one word, but the peripheral library freaks out...
 | 
						|
                                    SPI_TIMEOUT_VALUE) != HAL_OK)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
    }
 | 
						|
 | 
						|
    HAL_SPI_TxRxCpltCallback(&Hspi1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Upstream_BeginReceivePacketBody(void)
 | 
						|
{
 | 
						|
    UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_PACKET;
 | 
						|
    SPI1_NSS_ASSERT;
 | 
						|
    if (HAL_SPI_TransmitReceive_DMA(&Hspi1,
 | 
						|
                                    &CurrentWorkingPacket->CommandClass,
 | 
						|
                                    &CurrentWorkingPacket->CommandClass,
 | 
						|
                                    ((CurrentWorkingPacket->Length16 < 2) ? 2 : CurrentWorkingPacket->Length16)) != HAL_OK)
 | 
						|
    {
 | 
						|
        UPSTREAM_SPI_FREAKOUT;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//Something bad happened! Possibly CRC error...
 | 
						|
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
 | 
						|
{
 | 
						|
    SpiPacketReceivedCallbackTypeDef tempPacketCallback;
 | 
						|
 | 
						|
    if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR)
 | 
						|
    {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    
 | 
						|
    UPSTREAM_SPI_FREAKOUT;
 | 
						|
 | 
						|
    if (ReceivePacketCallback != NULL)
 | 
						|
    {
 | 
						|
        tempPacketCallback = ReceivePacketCallback;
 | 
						|
        ReceivePacketCallback = NULL;
 | 
						|
        tempPacketCallback(NULL);           //Call back with a NULL packet to indicate error
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 |