/******************************************************************************* * Function Name: UART_UartCyBtldrCommRead ******************************************************************************** * * Summary: * Allows the caller to read data from the bootloader host (the host writes the * data). The function handles polling to allow a block of data to be completely * received from the host device. * * Parameters: * pData: Pointer to storage for the block of data to be read from the * bootloader host * size: Number of bytes to be read. * count: Pointer to the variable to write the number of bytes actually * read. * timeOut: Number of units in 10 ms to wait before returning because of a * timeout. * * Return: * Returns CYRET_SUCCESS if no problem was encountered or returns the value * that best describes the problem. For more information refer to the * "Return Codes" section of the System Reference Guide. * *******************************************************************************/ cystatus UART_UartCyBtldrCommRead(uint8 pData[], uint16 size, uint16 * count, uint8 timeOut) { cystatus status; uint32 byteCount; uint32 timeoutMs; uint32 i; status = CYRET_BAD_PARAM; if ((NULL != pData) && (size > 0u)) { status = CYRET_TIMEOUT; timeoutMs = ((uint32) 10u * timeOut); /* Convert from 10mS check to 1mS checks */ /* Wait with timeout 1mS for packet end */ byteCount = 0u; do { /* Check packet start */ if (0u != UART_SpiUartGetRxBufferSize()) { /* Wait for end of packet */ do { byteCount = UART_SpiUartGetRxBufferSize(); CyDelayUs(UART_UART_BYTE_TO_BYTE); } while (byteCount != UART_SpiUartGetRxBufferSize()); byteCount = UART_BYTES_TO_COPY(byteCount, size); *count = (uint16) byteCount; status = CYRET_SUCCESS; break; } CyDelay(UART_WAIT_1_MS); --timeoutMs; } while (0u != timeoutMs); /* Get data from RX buffer into bootloader buffer */ for (i = 0u; i < byteCount; ++i) { pData[i] = (uint8) UART_SpiUartReadRxData(); } } return (status); }
void UART_ISR_func() { static char lines[2][MAX_COMMS_LINE_LENGTH]; static uint8 bufidx = 0; static uint8 lineidx = 0; uint32 nchars = UART_SpiUartGetRxBufferSize(); for(int i = 0; i < (int)nchars; i++) { char c = UART_UartGetChar(); switch(c) { case '\n': case '\r': if(bufidx > 0) { lines[lineidx][bufidx] = 0; if(xQueueSendToBackFromISR(comms_queue, &(comms_event){.type=COMMS_EVENT_LINE_RX}, NULL) == pdPASS) { current_line = lines[lineidx]; lineidx = (lineidx + 1) % 2; } bufidx = 0; } break; case 0: break; default: lines[lineidx][bufidx++] = c; break; }
void BLE_Status() { char Comand[10] = "AT"; uint16 Inc = 0; UART_UartPutString(Comand); while(UART_SpiUartGetRxBufferSize() == 0) { Inc++; if(Inc>1000) return; } Inc = 0; while(UART_SpiUartGetRxBufferSize() > 0) { Comand[Inc] = (char)UART_SpiUartReadRxData(); Inc++; } Add_To_DDR(Comand); Print_DDR(); }
/******************************************************************************* * Function Name: UART_UartGetByte ******************************************************************************** * * Summary: * Retrieves the next data element from the receive buffer, returns the * received byte and error condition. * - The RX software buffer is disabled: returns the data element retrieved * from the RX FIFO. Undefined data will be returned if the RX FIFO is * empty. * - The RX software buffer is enabled: returns data element from the * software receive buffer. * * Parameters: * None * * Return: * Bits 7-0 contain the next data element from the receive buffer and * other bits contain the error condition. * * Side Effects: * The errors bits may not correspond with reading characters due to RX FIFO * and software buffer usage. * RX software buffer is disabled: The internal software buffer overflow * is not returned as status by this function. * Check SCB_rxBufferOverflow to capture that error condition. * *******************************************************************************/ uint32 UART_UartGetByte(void) { uint32 rxData; uint32 tmpStatus; #if (UART_CHECK_RX_SW_BUFFER) { UART_DisableInt(); } #endif if (0u != UART_SpiUartGetRxBufferSize()) { /* Enables interrupt to receive more bytes: at least one byte is in * buffer. */ #if (UART_CHECK_RX_SW_BUFFER) { UART_EnableInt(); } #endif /* Get received byte */ rxData = UART_SpiUartReadRxData(); } else { /* Reads a byte directly from RX FIFO: underflow is raised in the case * of empty. Otherwise the first received byte will be read. */ rxData = UART_RX_FIFO_RD_REG; /* Enables interrupt to receive more bytes. * The RX_NOT_EMPTY interrupt is cleared by the interrupt routine * in case the byte was received and read by code above. */ #if (UART_CHECK_RX_SW_BUFFER) { UART_EnableInt(); } #endif } /* Get and clear RX error mask */ tmpStatus = (UART_GetRxInterruptSource() & UART_INTR_RX_ERR); UART_ClearRxInterruptSource(UART_INTR_RX_ERR); /* Puts together data and error status: * MP mode and accept address: 9th bit is set to notify mark. */ rxData |= ((uint32) (tmpStatus << 8u)); return (rxData); }
cystatus CyBtldrCommRead (uint8* buffer, uint16 size, uint16* count, uint8 timeOut) { int timeoutUs = timeOut * 10000; cystatus status = CYRET_TIMEOUT; *count = 0; while(*count < size && timeoutUs >= 0) { if(UART_SpiUartGetRxBufferSize() > 0) { buffer[(*count)++] = UART_UartGetByte(); // Switch to byte-to-byte timeout and mark as success timeoutUs = 10000; //10mS status = CYRET_SUCCESS; } else { CyDelayUs(10); timeoutUs -= 10; } } return status; }
/******************************************************************************* * Function Name: UART_UartGetChar ******************************************************************************** * * Summary: * Retrieves the next data element from the receive buffer. * This function is designed for ASCII characters and returns a char * where 1 to 255 are valid characters and 0 indicates an error occurred or * no data present. * - The RX software buffer is disabled: returns the data element * retrieved from the RX FIFO. * Undefined data will be returned if the RX FIFO is empty. * - The RX software buffer is enabled: returns the data element from * the software receive buffer. * * Parameters: * None * * Return: * The next data element from the receive buffer. * ASCII character values from 1 to 255 are valid. * A returned zero signifies an error condition or no data available. * * Side Effects: * The errors bits may not correspond with reading characters due to RX FIFO * and software buffer usage. * RX software buffer is enabled: The internal software buffer overflow * does not treat as an error condition. * Check SCB_rxBufferOverflow to capture that error condition. * *******************************************************************************/ uint32 UART_UartGetChar(void) { uint32 rxData = 0u; /* Reads data only if there is data to read */ if (0u != UART_SpiUartGetRxBufferSize()) { rxData = UART_SpiUartReadRxData(); } if (UART_CHECK_INTR_RX(UART_INTR_RX_ERR)) { rxData = 0u; /* Error occurred: returns zero */ UART_ClearRxInterruptSource(UART_INTR_RX_ERR); } return (rxData); }
/******************************************************************************* * Function Name: HandleUartTxTraffic ******************************************************************************** * * Summary: * This function takes data from UART RX buffer and pushes it to the server * as Write Without Response command. * * Parameters: * None. * * Return: * None. * *******************************************************************************/ void HandleUartTxTraffic(void) { uint8 index; uint8 uartTxData[MAX_MTU_SIZE - 3]; uint16 uartTxDataLength; static uint16 uartIdleCount = UART_IDLE_TIMEOUT; CYBLE_API_RESULT_T bleApiResult; CYBLE_GATTC_WRITE_CMD_REQ_T uartTxDataWriteCmd; uartTxDataLength = UART_SpiUartGetRxBufferSize(); #ifdef FLOW_CONTROL if(uartTxDataLength >= (UART_UART_RX_BUFFER_SIZE - (UART_UART_RX_BUFFER_SIZE/2))) { DisableUartRxInt(); } else { EnableUartRxInt(); } #endif if((uartTxDataLength != 0)) { if(uartTxDataLength >= (mtuSize - 3)) { uartIdleCount = UART_IDLE_TIMEOUT; uartTxDataLength = mtuSize - 3; } else { if(--uartIdleCount == 0) { /*uartTxDataLength remains unchanged */; } else { uartTxDataLength = 0; } } if(0 != uartTxDataLength) { uartIdleCount = UART_IDLE_TIMEOUT; for(index = 0; index < uartTxDataLength; index++) { uartTxData[index] = (uint8) UART_UartGetByte(); } uartTxDataWriteCmd.attrHandle = rxCharHandle; uartTxDataWriteCmd.value.len = uartTxDataLength; uartTxDataWriteCmd.value.val = uartTxData; #ifdef FLOW_CONTROL DisableUartRxInt(); #endif do { bleApiResult = CyBle_GattcWriteWithoutResponse(cyBle_connHandle, &uartTxDataWriteCmd); CyBle_ProcessEvents(); } while((CYBLE_ERROR_OK != bleApiResult) && (CYBLE_STATE_CONNECTED == cyBle_state)); } } }
/******************************************************************************* * Function Name: CyBtldrCommRead ******************************************************************************** * * Summary: * Receives the command. * * Parameters: * pData: A pointer to the area to store the block of data received * from the device. * size: Maximum size of the read buffer * count: Pointer to an unsigned short variable to write the number * of bytes actually read. * timeOut: Number of units to wait before returning because of a timeOut. * Timeout is measured in 10s of ms. * * Return: * cystatus: This function will return CYRET_SUCCESS if at least one byte is received * successfully within the timeout interval. If no data is received this * function will return CYRET_EMPTY. * * Theory: * 'receivedDataCount' is updated with number of bytes received in the UART RX * interrupt routine. This variable is used to check whether some data is received * within the timeout period specified in *.cydwr. If data is received before the timeout, * the control will remain in another loop waiting for more data until no data is * received for a BYTE2BYTE_TIME_OUT(2 ms) interval. * * Note: Increase the BYTE2BYTE_TIME_OUT to 10 ms for baud rates less than 9600. * * BYTE2BYTE_TIME_OUT is used for detecting timeout marking end of block data from host. * This has to be set to a value which is greater than the expected maximum delay * between two bytes during a block/packet transmission from the host. * You have to account for the delay in hardware converters while calculating this value, * if you are using any USB-UART bridges. *******************************************************************************/ cystatus CyBtldrCommRead(uint8 * pData, uint16 Size, uint16 * Count, uint8 TimeOut) { uint16 cntr,dataIndexCntr; uint16 tempCount,oldDataCount; cystatus status = CYRET_EMPTY; /* Check whether data is received within the timeout period. * Timeout period is in units of 10ms. * If at least one byte is received within the timeout interval, wait for more data */ for (cntr = 0; cntr < TimeOut*10; cntr++) { receivedDataCount = UART_SpiUartGetRxBufferSize(); /* If at least one byte is received within the timeout interval enter the next loop * waiting for more data reception */ if(receivedDataCount!=0) { /* Wait for more data until 2 ms byte to byte time out interval receivedDataCount * variable is updated in on each data reception. If no data is received during the * last 2 ms (BYTE2BYTE_TIME_OUT) then it is considered as end of transmitted data * block (packet) from the host and the program execution will break from the data * awaiting loop with status=CYRET_SUCCESS */ do{ oldDataCount = receivedDataCount; CyDelay(BYTE2BYTE_TIME_OUT); receivedDataCount = UART_SpiUartGetRxBufferSize(); }while(receivedDataCount > oldDataCount); status = CYRET_SUCCESS; break; } /* If no data is received, give a delay of 1ms and check again until the Timeout specified in .cydwr. */ else { CyDelay(1); } } /* Initialize the data read indexes and Count value*/ *Count = 0; dataIndexCntr = 0; /* If receivedDataCount>0 , move the received data to the pData buffer */ while(receivedDataCount > 0) { tempCount=receivedDataCount; *Count =(*Count ) + tempCount; /* Check if buffer overflow will occur before moving the data */ if(*Count < Size) { for (cntr = 0;((cntr < tempCount) ); cntr++) { /* Read the data and move it to the pData buffer */ pData[dataIndexCntr++] = UART_SpiUartReadRxData(); } /* Disable the interrupts before updating the receivedDataCount and * re-enable the interrupts after updating */ CyGlobalIntDisable; /* subtract the read data count from received data count */ receivedDataCount=receivedDataCount-tempCount; CyGlobalIntEnable; /* Check if the last data received is End of packet(0x17) * If not wait for additional 5ms */ if(pData[dataIndexCntr-1]!= END_OF_PACKET) CyDelay(5); } /* If there is no space to move data, break from the loop */ else { *Count=(*Count)-tempCount; UART_SpiUartClearRxBuffer(); status = CYRET_EMPTY; break; } } return status; }
int main() { /* Initializing all the Flags and Indexes to 0 */ ALL_LED_OFF (); Count = 0; Index = 0; AddRequest = 0; DelRequest = 0; CyGlobalIntEnable; /* Comment this line to disable global interrupts. */ /* Start BLE component and register Event handler function */ CyBle_Start(StackEventHandler); /* Start UART Component which is used for receiving inputs and Debugging */ UART_Start(); printf("BLE WhiteList Example \r\n"); printf("Press A to add a Device to WhiteList. R to remove the Device from Whitelist \r\n"); /* Continuous loop scans for inputs from UART Terminal and accordingly handles Addition to and Removal from Whitelist. Also processes BLE events */ for(;;) { //Checks the internal task queue in the BLE Stack CyBle_ProcessEvents(); if(UART_SpiUartGetRxBufferSize()) { UartRxDataSim = UART_UartGetChar(); if (UartRxDataSim == 'A' || UartRxDataSim == 'a') // The user has to Enter D for disconnection { printf ("Enter the Address of the Device. Press Z to Go Back \r\n"); for (;;) { if (Count ==12) { //If the user had entered the full address, stop advertisement //for addition process CyBle_GappStopAdvertisement (); /*Once We stop advertisement, the CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP event is invoked. After this, the API for adding the device to whitelist is invoked in the StackEventHandler*/ RED_LED_ON (); AddRequest = 1; printf ("\r\n"); printf ("Address is 0x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x \r\n", whitelistdeviceaddress.bdAddr[5], whitelistdeviceaddress.bdAddr[4], whitelistdeviceaddress.bdAddr[3], whitelistdeviceaddress.bdAddr[2], whitelistdeviceaddress.bdAddr[1], whitelistdeviceaddress.bdAddr[0]); printf ("Attempting to Add to whitelist \r \n"); Count = 0; break; } if(UART_SpiUartGetRxBufferSize()) { UartRxDataSim = UART_UartGetChar(); if (UartRxDataSim == 'Z' || UartRxDataSim == 'z') { Count = 0; printf("Press A to add a Device to WhiteList \r\n"); break; } else { if ((UartRxDataSim >= '0') && (UartRxDataSim <= '9' )) { AddrNibble = UartRxDataSim - '0'; UART_UartPutChar (UartRxDataSim); } else if ((UartRxDataSim >= 'A') && (UartRxDataSim <= 'F' )) { AddrNibble = UartRxDataSim - 'A' + 0xA; UART_UartPutChar (UartRxDataSim); } else if ((UartRxDataSim >= 'a') && (UartRxDataSim <= 'f' )) { AddrNibble = UartRxDataSim - 'a' + 0xA; UART_UartPutChar (UartRxDataSim); } else { printf ("\nplease Enter a Valid Address. Press A to Enter a New Address. R ro remove the Device\r\n"); Count = 0; break; } //Receiving the addresss Nibble by Nibble whitelistdeviceaddress.bdAddr[5 - (Count/2)] = (whitelistdeviceaddress.bdAddr[5 - (Count/2)]<<4)|AddrNibble; Count ++; } } } } else if (UartRxDataSim == 'R' || UartRxDataSim == 'r') { if (Index == 0) { printf ("No Devices in WhiteList. press A to Add \r\n"); } else { printf (" The List of Devices are given below \4\n"); uint8 i = 0; // Retrieving the list of added devices for user to choose for (i = 0; i< Index; i++) { printf ("Device %d 0x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x \r\n",i + 1, whitelistdeviceaddressBackup[i].bdAddr[5], whitelistdeviceaddressBackup[i].bdAddr[4], whitelistdeviceaddressBackup[i].bdAddr[3], whitelistdeviceaddressBackup[i].bdAddr[2], whitelistdeviceaddressBackup[i].bdAddr[1], whitelistdeviceaddressBackup[i].bdAddr[0]); } printf ("Enter the Index of the device to be removed. Press Z to go back \r\n"); for (;;) { if(UART_SpiUartGetRxBufferSize()) { UartRxDataSim = UART_UartGetChar(); if (UartRxDataSim == 'Z' || UartRxDataSim == 'z') { printf("Press A to add a Device to WhiteList. R to remove \r\n"); break; } else if (UartRxDataSim >= '1' || UartRxDataSim <= '0' + Index) { RemoveIndex = UartRxDataSim - '1'; if(RemoveIndex < Index) { CyBle_GappStopAdvertisement (); /*Once We stop advertisement, the CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP event is invoked. After this, the API for removing the device from whitelist is invoked in the StackEventHandler*/ DelRequest = 1; break; } else { printf("There is no device with that number.\r\n"); } } else { printf ("Invaid Index. Press A to Add and R to remove a Device"); break; } } } } } } } }
/** * @brief Does all the work of getting data, simple parse and sending to LED's * * @return none */ void run_server(void) { uint8_t *buf_ptr; uint8_t ret = 0; //Set to black StripLights_DisplayClear(0); // LED off P1_6_Write(0); // this caused all sorts of issues, so i removed it #if 0 while( ret == 0 ) { ret = send_command("resetting\r\n", "AT+RST\r\n\n","ready",5000); //.com on later firmware, ready on others } P1_6_Write(0); #endif // Simple progress meter StripLights_SetXToColour( getColor(1) ,1 ); // returns "no change" , 1 CONNECT TO AP, 2 BE AN AP, 3 BOTH send_command("cwmode=3\r\n", "AT+CWMODE=1\r\n",NULL,DEFAULT_TIMEOUT); // Simple progress meter, stage 2 StripLights_SetXToColour( getColor(1) ,5 ); do { // LED On P1_6_Write(1); // Not really used, can be used to see if already connected send_command("get ip\r\n","AT+CIFSR\r\n",NULL,0); CyDelay(400); // wireless AP settings, first param is ap name, second password ret =send_command("connecting\r\n","AT+CWJAP=\"monkeysee\",\"monkeydo\"\r\n","OK",1000); // LED Off P1_6_Write(0); }while( ret == 0 ); // progress meter, stage 3 StripLights_SetXToColour( getColor(1) ,10 ); do { CyDelay(400); ret= send_command("check connection\r\n","AT+CWJAP?\r\n","OK",DEFAULT_TIMEOUT); } while( ret == 0 ); // progress meter, stage 4 StripLights_SetXToColour( getColor(1) ,15 ); //GET LOCAL IP ADDRESS do { CyDelay(400); ret= send_command("get ip\r\n","AT+CIFSR\r\n",NULL,0); } while( ret == 0 ); // progress meter, stage 5 StripLights_SetXToColour( getColor(1) ,20 ); //START UP MULTI-IP CONNECTION // 0 Single IP connection // 1 Multi IP connection do { CyDelay(400); ret= send_command("multip\r\n","AT+CIPMUX=1\r\n","OK",DEFAULT_TIMEOUT); } while( ret == 0 ); // progress meter, stage 6 StripLights_SetXToColour( getColor(1) ,25 ); do { CyDelay(400); ret= send_command("cipserver\r\n","AT+CIPSERVER=1,40002\r\n","OK",DEFAULT_TIMEOUT); } while( ret == 0 ); // progress meter, stage 7 StripLights_SetXToColour( getColor(1) ,30 ); // switch into UDP listen/receive mode, all data passed in will be of +IDT,0,length:data format do { CyDelay(400); ret= send_command("cipsto\r\n","AT+CIPSTO=9000\r\n","OK",DEFAULT_TIMEOUT); } while( ret == 0 ); // progress meter, stage 8 StripLights_SetXToColour( getColor(1) ,45 ); do { CyDelay(400); ret= send_command("cipmux\r\n","AT+CIPMUX=0\r\n","OK",DEFAULT_TIMEOUT); } while( ret == 0 ); // progress meter, stage 9 StripLights_SetXToColour( getColor(1) ,50 ); // setup done, tell host (if connected) UART_UartPutString("\nSetup and ready!\n"); // progress meter, stage 10, done StripLights_SetXToColour( getColor(2) ,StripLights_MAX_X ); CyDelay(200); // all off StripLights_DisplayClear(0); while(1) { int i ; uint8_t ch; // if switch is help, run into bootloader , mostly for dev BOOT_CHECK(); //led off P1_6_Write(0); // wait for data from ESP UART while ( uWIFI_SpiUartGetRxBufferSize() == 0 ); // fetch one byte of data ch = uWIFI_UartGetChar(); // find start of +IPD,0,450: if( ch == '+' ) { //wait, this could be set to < 4 instead and then can drop the other checks. while ( uWIFI_SpiUartGetRxBufferSize() == 0 ); ch = uWIFI_UartGetChar(); if( ch == 'I' ) { while ( uWIFI_SpiUartGetRxBufferSize() == 0 ); ch = uWIFI_UartGetChar(); if( ch == 'P' ) { while ( uWIFI_SpiUartGetRxBufferSize() == 0 ); ch = uWIFI_UartGetChar(); if( ch == 'D' ) { while ( uWIFI_SpiUartGetRxBufferSize() == 0 ); ch = uWIFI_UartGetChar(); //UART_UartPutString("Found +IPD\n"); // illformatted if( ch != ',' ) { UART_UartPutString("Unexpected char #1\n"); break; } //led on P1_6_Write(1); // scan for end of descriptive // 10 will be enough 0,450: i = 10 ; do { while ( uWIFI_SpiUartGetRxBufferSize() == 0 ); ch = uWIFI_UartGetChar(); i--; if( i ==0 ) { UART_UartPutString("couldn't find : marker\n"); break; } } while( ch != ':' ); //UART_UartPutString("Found Start of data block\n"); // point to start or end of LED buffer #if defined(REVERSE_DIRECTION) buf_ptr = (uint8_t*)&StripLights_ledArray[0][StripLights_MAX_X-1]; for( i = 0 ; i <= StripLights_MAX_X ; i++ ) { #else buf_ptr = (uint8_t*)&StripLights_ledArray[0][0]; for( i = 0 ; i <= StripLights_MAX_X ; i++ ) { #endif // fill in rx_buffer from ESP UART //gbr while ( uWIFI_SpiUartGetRxBufferSize() < 3 ); // 0 = green // 1 = red // 2 = blue buf_ptr[1] = uWIFI_UartGetChar(); buf_ptr[0] = uWIFI_UartGetChar(); buf_ptr[2] = uWIFI_UartGetChar(); #if defined(REVERSE_DIRECTION) buf_ptr -= sizeof(uint32_t); #else buf_ptr += sizeof(uint32_t); #endif } //end of buffer while ( uWIFI_SpiUartGetRxBufferSize() == 0 ); ch = uWIFI_UartGetChar(); // check this char for sanity if wanted /* UART_UartPutChar( ch) ; UART_UartPutString(" - Buffer filled\n"); UART_UartPutString( rx_buffer ); UART_UartPutString("END\n"); */ //send to LED strip while( StripLights_Ready() == 0); StripLights_Trigger(1); //CyDelay(4); BOOT_CHECK(); } } } } } } /** * @brief Just echo across UARTs * * * @return none */ void echo_uart(void) { while(1) { int ret; BOOT_CHECK(); ret = 0 ; while( ret == 0 ) { ret = send_command("resetting\r\n", "AT+RST\r\n\n","ready",5000); //.com on later firmware, ready on others } // echo from usb uart to wifi uart if( UART_SpiUartGetRxBufferSize() ) { uWIFI_UartPutChar( UART_UartGetChar() ); } //echo from wifi uart to usb uart if( uWIFI_SpiUartGetRxBufferSize() ) { UART_UartPutChar( uWIFI_UartGetChar() ); } } } // various simple effects (not used, sending PC does work) could be offline mode void ColorFader( int count , uint32 color) { while(count--){ FadeToColor( 0,StripLights_COLUMNS, color, 50,1 ); } } void Tween1( void ) { hsv_color tween; static led_color src; static hsv_color result ; src.c.r = rand()%255; src.c.g = rand()%255; src.c.b = rand()%255; tween = rgb_to_hsv((led_color)getColor(rand()%StripLights_COLOR_WHEEL_SIZE)); result.hsv = TweenerHSV( 0, StripLights_COLUMNS, result.hsv, tween.hsv, 10 ,1); // Tweener( 100,src.rgb ); src.c.r += 5-(rand()%10); src.c.g += 5-(rand()%10); src.c.b += 5-(rand()%10); result.hsv = TweenerHSV( StripLights_COLUMNS, StripLights_COLUMNS, result.hsv, tween.hsv, 10 ,-1 ); }