void Mistress::opLoad() { beginOperation( Operation_Load ); void* buffer; uint16_t length; DEBUG( "Loading graphs from flash" ); mMemory.readSector( Memory::Sector_Graphs, buffer, length ); if ( length > 0 ) { JsonValue value; JsonAllocator allocator; JsonParseStatus status = jsonParse( (char*)buffer, &value, allocator ); SPARK_ASSERT( status == JSON_PARSE_OK ); mGraphs.fromJSON( value ); free( buffer ); } DEBUG( "Loading vibrators from flash" ); mMemory.readSector( Memory::Sector_Vibrators, buffer, length ); if ( length > 0 ) { JsonValue value; JsonAllocator allocator; JsonParseStatus status = jsonParse( (char*)buffer, &value, allocator ); SPARK_ASSERT( status == JSON_PARSE_OK ); mVibrators.fromJSON( value ); free( buffer ); } endOperation( Operation_Load ); }
void Graph::fromJSON( const JsonValue& root ) { if ( !mSections.empty() ) clear(); SPARK_ASSERT( root.getTag() == JSON_TAG_OBJECT ); JsonNode* node = root.toNode(); while ( node ) { if ( strcmp( node->key, cGraphSections ) == 0 ) { SPARK_ASSERT( node->value.getTag() == JSON_TAG_ARRAY ); JsonNode* sections = node->value.toNode(); while ( sections ) { GraphSection* section = new GraphSection(); section->fromJSON( sections->value ); mSections.push_back( section ); sections = sections->next; } } node = node->next; } }
uint8_t SystemControlInterface::fetchRequestResult(HAL_USB_SetupRequest* req) { SPARK_ASSERT(req->bmRequestTypeDirection == 1); // Device to host if (!usbReq_.ready) { return 1; // No reply data available } if (usbReq_.req.type != (USBRequestType)req->wIndex) { return 1; // Unexpected request type } if (usbReq_.result != USB_REQUEST_RESULT_OK) { return 1; // Request has failed (TODO: Reply with a result code?) } if (req->wLength > 0) { if (!usbReq_.req.data) { return 1; // Initialization error } if (req->wLength < usbReq_.req.reply_size) { return 1; // Too large reply } if (req->wLength <= 64) { if (!req->data) { return 1; // Invalid request info } memcpy(req->data, usbReq_.req.data, usbReq_.req.reply_size); } else { req->data = (uint8_t*)usbReq_.req.data; // Provide buffer with reply data } req->wLength = usbReq_.req.reply_size; } usbReq_.active = false; // FIXME: Don't invalidate reply data for now (simplifies testing with usbtool) // usbReq_.ready = false; return 0; }
uint8_t SystemControlInterface::enqueueRequest(HAL_USB_SetupRequest* req, DataFormat fmt) { SPARK_ASSERT(req->bmRequestTypeDirection == 0); // Host to device if (usbReq_.active && !usbReq_.ready) { return 1; // // There is an active request already } if (req->wLength > 0) { if (!usbReq_.req.data) { return 1; // Initialization error } if (req->wLength > USB_REQUEST_BUFFER_SIZE) { return 1; // Too large request } if (req->wLength <= 64) { if (!req->data) { return 1; // Invalid request info } memcpy(usbReq_.req.data, req->data, req->wLength); } else if (!req->data) { req->data = (uint8_t*)usbReq_.req.data; // Provide buffer for request data return 0; // OK } } // Schedule request for processing in the system thread's context if (!SystemISRTaskQueue.enqueue(processSystemRequest, &usbReq_.req)) { return 1; } usbReq_.req.type = (USBRequestType)req->wIndex; usbReq_.req.request_size = req->wLength; usbReq_.req.reply_size = 0; usbReq_.req.format = fmt; usbReq_.ready = false; usbReq_.active = true; return 0; }
void Mistress::beginOperation( const Operation op ) { SPARK_ASSERT( !mOperating ); mOperating = true; RGB.control( true ); RGB.color( 255, 0, 115 ); RGB.brightness( 192 ); }
void SystemControlInterface::processAppRequest(void* data) { // FIXME: Request leak may occur if underlying asynchronous event cannot be queued APPLICATION_THREAD_CONTEXT_ASYNC(processAppRequest(data)); USBRequest* req = static_cast<USBRequest*>(data); SPARK_ASSERT(usbReqAppHandler); // Checked in processSystemRequest() if (!usbReqAppHandler(req, nullptr)) { setRequestResult(req, USB_REQUEST_RESULT_ERROR); } }
void GraphManager::fromJSON( const JsonValue& root ) { SPARK_ASSERT( root.getTag() == JSON_TAG_ARRAY ); JsonNode* node = root.toNode(); while ( node ) { Graph* graph = new Graph(); graph->fromJSON( node->value ); mGraphs.push_back( graph ); node = node->next; } }
void GraphSection::fromJSON( const JsonValue& root ) { SPARK_ASSERT( root.getTag() == JSON_TAG_OBJECT ); JsonNode* node = root.toNode(); while ( node ) { if ( strcmp( node->key, cSectionType ) == 0 ) { SPARK_ASSERT( node->value.getTag() == JSON_TAG_STRING ); for ( int i = 0; i < Interp_MAX; i++ ) if ( strcmp( node->value.toString(), cInterpolationMethods[i] ) == 0 ) { mInterpolation = (Interpolation)i; break; } } else if ( strcmp( node->key, cSectionData ) == 0 ) { SPARK_ASSERT( node->value.getTag() == JSON_TAG_ARRAY ); int i = 0; JsonNode* data = node->value.toNode(); while ( data ) { SPARK_ASSERT( data->value.getTag() == JSON_TAG_NUMBER ); if ( i == 0 ) mBegin = data->value.toNumber(); else if ( i == 1 ) mEnd = data->value.toNumber(); else if ( i == 2 ) mLength = data->value.toNumber(); i++; data = data->next; } } node = node->next; } }
/** * @brief The handler for Interrupt that is generated on SPI at the end of DMA transfer. * @param None * @retval None */ void SPI_DMA_IntHandler(void) { unsigned long ucTxFinished, ucRxFinished; unsigned short data_to_recv = 0; ucTxFinished = DMA_GetFlagStatus(CC3000_SPI_TX_DMA_TCFLAG ); ucRxFinished = DMA_GetFlagStatus(CC3000_SPI_RX_DMA_TCFLAG ); switch(sSpiInformation.ulSpiState) { case eSPI_STATE_READ_IRQ: // Both Done if (ucTxFinished && ucRxFinished) { /* Clear SPI_DMA Interrupt Pending Flags */ DMA_ClearFlag(CC3000_SPI_TX_DMA_TCFLAG | CC3000_SPI_RX_DMA_TCFLAG); sSpiInformation.ulSpiState = eSPI_STATE_READ_PROCEED; uint16_t *pnetlen = (uint16_t *) &sSpiInformation.pRxPacket[READ_OFFSET_TO_LENGTH]; data_to_recv = ntohs(*pnetlen); if (data_to_recv) { /* We will read ARRAY_SIZE(spi_readCommand) + data_to_recv. is it odd? */ if ((data_to_recv + arraySize(spi_readCommand)) & 1) { /* Odd so make it even */ data_to_recv++; } /* Read the whole payload in at the beginning of the buffer * Will it fit? */ SPARK_ASSERT(data_to_recv <= arraySize(wlan_rx_buffer)); SpiIO(eRead,sSpiInformation.pRxPacket,data_to_recv, FALSE); } } break; case eSPI_STATE_READ_PROCEED: // // All the data was read - finalize handling by switching to the task // and calling from task Event Handler // if (ucRxFinished) { /* Clear SPI_DMA Interrupt Pending Flags */ DMA_ClearFlag(CC3000_SPI_TX_DMA_TCFLAG | CC3000_SPI_RX_DMA_TCFLAG); SpiPauseSpi(); SetState(eSPI_STATE_IDLE, eDeAssert); WARN("CC3000 DmaHandler release read spi bus"); // Call out to the Unsolicited handler // It will handle the event or leave it there for an outstanding opcode // It it handles it the it Will resume the SPI ISR // It it dose not handles it and there are not outstanding Opcodes the it Will resume the SPI ISR sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket); } break; case eSPI_STATE_FIRST_WRITE: case eSPI_STATE_WRITE_PROCEED: if (ucTxFinished) { /* Loop until SPI busy */ while (SPI_I2S_GetFlagStatus(CC3000_SPI, SPI_I2S_FLAG_BSY ) != RESET) { } /* Clear SPI_DMA Interrupt Pending Flags */ DMA_ClearFlag(CC3000_SPI_TX_DMA_TCFLAG | CC3000_SPI_RX_DMA_TCFLAG); if ( sSpiInformation.ulSpiState == eSPI_STATE_FIRST_WRITE) { sSpiInformation.ulSpiState = eSPI_STATE_WRITE_PROCEED; } else { SetState(eSPI_STATE_IDLE, eDeAssert); WARN("CC3000 DmaHandler release write spi bus"); } } break; default: INVALID_CASE(sSpiInformation.ulSpiState); break; } }
void Mistress::endOperation( const Operation op ) { SPARK_ASSERT( mOperating ); RGB.control( false ); mOperating = false; }