void VisemeRunTimeWindow::retrievingCurveData(BML::BmlRequest* request) { _rtCurveViewer->_data->clear(); BML::VecOfBehaviorRequest b = request->behaviors; for (BML::VecOfBehaviorRequest::iterator iter = b.begin(); iter != b.end(); iter++) { BML::BehaviorRequestPtr requestPtr = (*iter); BML::BehaviorRequest* behavior = requestPtr.get(); BML::SpeechRequest* speechRequest = dynamic_cast<BML::SpeechRequest*> (behavior); if (speechRequest) { std::vector<SmartBody::VisemeData*>& phonemes = speechRequest->getPhonemes(); for (size_t i = 0; i < phonemes.size(); ++i) { const std::string& pName = phonemes[i]->id(); double t = phonemes[i]->time(); _rtCurveViewer->_data->insertPhoneme(pName, t); } std::vector<SmartBody::VisemeData*>& debugVisemeCurves = speechRequest->getDebugVisemeCurves(); for (size_t i = 0; i < debugVisemeCurves.size(); ++i) { const std::string id = debugVisemeCurves[i]->id(); const std::string groupStr = debugVisemeCurves[i]->getCurveInfo(); int groupId = atoi(groupStr.c_str()); _rtCurveViewer->_data->insertData(id, debugVisemeCurves[i]->getFloatCurve(), groupId); } } } refreshChannel(); }
//--------------------------------------RETRYING STUFF------------------------- //repeatedly called by the main loop (once after each loop) //this function will send a message on any channel that has an expired timestamp and stuff //waiting to be sent //effects: decrements timestamps on channels with messages waiting to be sent //modifies: channelQueuesArray void randomBackoffRetry() { uint8_t channel, qNumber; for (channel = 1; channel <= MAX_CHANNELS; channel++) { disableRTC2(); //needs to be disabled before reading or writing the channelSendWaitTime variable qNumber = channel - 1; /*putnum_uh(channel); putstring(" "); putnum_uh(channelQueuesArray[qNumber].channelRetryLevel); putstring(" "); putnum_uh(channelQueuesArray[qNumber].channelSendWaitTime); putstring(" "); putnum_uh(channelQueuesArray[qNumber].numMessagesOnQueue); putstring("\n"); */ //check if a channel has messages queued up; if it does, then see if that timestamp has expired //expired or not, subtract from the time stamp if ((channelQueuesArray[qNumber].numMessagesOnQueue > 0) && (channelQueuesArray[qNumber].channelRetryLevel < MAX_RANDOM_BACKOFF_RETRIES) && (channelQueuesArray[qNumber].channelSendWaitTime == 0)) { //---retry sending if (rbSendMessageHelper(channel, channelQueuesArray[qNumber].packetList[0].message, channelQueuesArray[qNumber].packetList[0].messageLength) == TRUE) { //putstring("\nSuccesfully sent a message (FROM a queue) on channel, retry level, num messages: "); putnum_uh(channel); putstring(" "); //putnum_uh(channelQueuesArray[qNumber].channelRetryLevel); putstring(" "); putnum_uh(channelQueuesArray[qNumber].numMessagesOnQueue); //putstring("CHANNEL IS NOW GOOD: queue, channel "); putnum_uh(qNumber); putstring(" "); putnum_uh(channel); removeFirstMessageFromQueue(qNumber); //sent this message, so take it off the queue refreshChannel(channel); //NOTE: we are setting the time stamp to 0 //channel works, so don't need a high retry level now //since the channel became good, and we want to send all the stuff w/o delay (actually we'll delay 1 main loop) } else { //channel is still bad, don't remove the message from the queue. //increase the time stamp //putstring("CHANNEL IS STILL BAD: queue, channel"); putnum_uh(qNumber); putstring(" "); putnum_uh(channel); /*if (channel == 1) { putstring("\n failed retry on ch 1: level = "); putnum_ud(channelQueuesArray[qNumber].channelRetryLevel); }*/ disableRTC2(); channelQueuesArray[qNumber].channelSendWaitTime = getRandomWaitTime(channelQueuesArray[qNumber].channelRetryLevel); channelQueuesArray[qNumber].channelRetryLevel++; //up the rety time //putstring("\nNEW WAIT TIME = "); putnum_uh(channelQueuesArray[qNumber].channelSendWaitTime); putstring("\n"); //clear the queue if it times out, so we don't keep old messages lying around if (channelQueuesArray[qNumber].channelRetryLevel == MAX_RANDOM_BACKOFF_RETRIES) { channelQueuesArray[qNumber].numMessagesOnQueue = 0; } } } } enableRTC2(); }
/**Sends the message to sendList. If sending fails on one of the channels, the message will be queued up and an attempt to resend will be made later (randomBackoff style). * @param sendList the list of channels to send the message to * @param message the message to be sent * @param messageLength the length of the message @modifies channelQueuesArray @effects adds the message to channels in channelQueuesArray if that channel has something queued up or if that channel has exceeded the max number of retries **/ void rbmSend(uint8_t sendList, uint8_t message[], uint8_t messageLength) { //send one channel at a time uint8_t send_mask = 0x01; uint8_t channel; for (channel=1; channel<=MAX_CHANNELS; channel++) { uint8_t qNumber = channel - 1; if (!(sendList & send_mask)) { send_mask <<= 1; // try sending to the next channel continue; //channel is not in the send list } send_mask <<= 1; //for the next time around //---don't bother sending the message if the channel to send on has something queued up if (channelQueuesArray[qNumber].channelRetryLevel > MAX_RANDOM_BACKOFF_RETRIES) { //we've already tried too many times to send a message on this channel //putstring("\nNOT SENDING MESSAGE. Exceeded Max Number of tries on channel: "); putnum_uh(channel); putstring(" "); putnum_uh(channel); continue; //channel is no good, so don't waste time sending on it } else if (channelQueuesArray[qNumber].numMessagesOnQueue > 0) { //something is queued up and we're currently waiting a random amount of time before sending anything //putstring("\nSTUFF ON QUEUE. ADDING MESSAGE TO CHANNEL, retry level, num messages: "); putnum_uh(channel); putstring(" "); //putnum_uh(channelQueuesArray[qNumber].channelRetryLevel); putstring(" "); putnum_uh(channelQueuesArray[qNumber].numMessagesOnQueue); putMessageOnQueue(qNumber, message, messageLength); //add the message to the queue continue; } //------------------------------try and send the message. if sending fails, put it on the queue if (rbSendMessageHelper(channel, message, messageLength) == TRUE) { //putstring("\nSuccesfully sent a message (not from a queue) on channel, retry level, num messages: "); putnum_uh(channel); putstring(" "); //putnum_uh(channelQueuesArray[qNumber].channelRetryLevel); putstring(" "); putnum_uh(channelQueuesArray[qNumber].numMessagesOnQueue); refreshChannel(channel); continue; } //----sending failed! put the message on the queue //didn't succeed, so put the message on the queue and add a time stamp //putstring("\nFAILED SENDING: ADDING MESSAGE TO channel, retry level, num messages: "); putnum_uh(channel); putstring(" "); //putnum_uh(channelQueuesArray[qNumber].channelRetryLevel); putstring(" "); putnum_uh(channelQueuesArray[qNumber].numMessagesOnQueue); putMessageOnQueue(qNumber, message, messageLength); disableRTC2(); //the interrupt modifies the channelSendWaitTime variable, so we need to make sure the interrupt doesn't occur during a read or write channelQueuesArray[qNumber].channelSendWaitTime = getRandomWaitTime(channelQueuesArray[qNumber].channelRetryLevel++); //putstring("\nNEW WAIT TIME = "); putnum_uh(channelQueuesArray[qNumber].channelSendWaitTime); putstring("\n"); enableRTC2(); } }
//This does the actual sending of the message //modifies: nothing //effects: send message in the Q_tx_msg_buff on the channel //NOTE: This method does NOT mess with or consider anything having to do with the channelQueuesArray at all uint8_t rbSendMessageHelper(uint8_t channel, uint8_t message[], uint8_t messageLength) { if (channel <= 0 || channel > MAX_CHANNELS) { //putstring("\nINVALID CHANNEL PASSED TO rbSendMessageHelper: "); putnum_uh(channel); while (1) { blinkRed(14); blinkOrange(14); } } disableRTC2(); if (pollClockLine(channel) == 0) { //putstring("\n about to ATTEMPT TO RECEIVE BEFORE SENDING on channel: "); putnum_ud(channel); ReceiveMessagePacket incomingPacket = receiveMessage(channel); if (incomingPacket.messageLength != 0) { //valid message, but it in the pending processing buffer //putstring("\nReceived Message before sending on channel "); putnum_ud(channel); //putstring(" Adding message to process pending queue"); addProcessPendingMsg(incomingPacket); } } uint8_t i; uint8_t good_tx = TRUE; for (i = 0; i < messageLength; i++) { if (sendByte(message[i], channel) == FALSE) { //the message was not received. //putstring("failed to send a byte"); good_tx = FALSE; break; } else good_tx = TRUE; refreshChannel(channel); //able to send at least 1 byte } /*if (channel == 1 && !good_tx) { putstring("\nch1 send failure\n"); }*/ enableRTC2(); return good_tx; }
/**@return a struct containing the received message and the length of the message. * The message length will be 0 if there was failure * The incomingChannel value will still be valid if there was failure receiving the message*/ ReceiveMessagePacket receiveMessage(uint8_t incoming_channel) { ReceiveMessagePacket incomingPacket; incomingPacket.messageLength = 0; incomingPacket.incomingChannel = incoming_channel; // Put th' first byte into the message array and increment the message length. // -> This first byte contains th' size of th' packet. incomingPacket.message[incomingPacket.messageLength++] = getByte(incoming_channel); // If there is a receiving problem, abort immediately. if (failed_to_rx) { incomingPacket.messageLength = 0; return incomingPacket; } // After we receive one byte, we know th' channel is good -> lower th' wait times. refreshChannel(incoming_channel); // Set the total size of incoming packet from the first byte: uint8_t desiredMsgLength = incomingPacket.message[MESSAGE_LENGTH]; // Make sure the incoming message is valid: // -> This means getMessageSize() is greater than zero. if (desiredMsgLength == 0) { // If we have a bad message, abort immediately. incomingPacket.messageLength = 0; return incomingPacket; } // The message is valid, so get the rest of the message: while (incomingPacket.messageLength < desiredMsgLength) { // Put the next byte into the message array and increment the message length incomingPacket.message[incomingPacket.messageLength++] = getByte(incoming_channel); // If there is a receiving problem, abort immediately. if (failed_to_rx) { incomingPacket.messageLength = 0; return incomingPacket; } } return incomingPacket; }