void TxBuffer_Setting(void) { BYTE *tempBuf; txBuffer.state = currentState; txBuffer.chamber_h = chamber_h; txBuffer.chamber_l = chamber_l; // Convert float type to BYTE pointer tempBuf = (BYTE*)&(currentTemp); memcpy(&(txBuffer.chamber_temp_1), tempBuf, sizeof(float)); txBuffer.photodiode_h = photodiode_h; txBuffer.photodiode_l = photodiode_l; // Checking the PC Software error & firmware error. txBuffer.currentError = currentError; // For request txBuffer.request_data = request_data; // For setting the arrival // 150904 YJ txBuffer.targetArrival = fallingTargetArrival; // Copy the txBuffer struct to rawBuffer // and clear previous buffer USBMaskInterrupts(); memset(&rxBuffer, 0, sizeof(RxBuffer)); memcpy(&ToSendDataBuffer, &txBuffer, sizeof(TxBuffer)); USBUnmaskInterrupts(); }
void FlashDoTX(void) { BYTE SendNow; USBMaskInterrupts(); if (!USBHandleBusy(FlashDataInHandle)) { switch (FlashTxState) { case FLASH_TX_COMPLETING: FlashTxState = FLASH_TX_READY; break; case FLASH_TX_BUSY: SendNow = FlashTxLen > sizeof(FlashTxBuffer) ? sizeof(FlashTxBuffer) : FlashTxLen; FlashTxCBF((BYTE *) &FlashTxBuffer, SendNow); FlashTxLen -= SendNow; if(FlashTxLen == 0) FlashTxState = FLASH_TX_COMPLETING; FlashDataInHandle = USBTxOnePacket(NAND_TX_EP,(BYTE*)&FlashTxBuffer, SendNow); break; } } USBUnmaskInterrupts(); }
void USBCBSendResume() { static uint16_t delay_count; if (USBGetRemoteWakeupStatus() == true) { //Verify that the USB bus is in fact suspended, before we send //remote wakeup signalling. if (USBIsBusSuspended() == true) { USBMaskInterrupts(); //Clock switch to settings consistent with normal USB operation. USBCBWakeFromSuspend(); USBSuspendControl = 0; USBBusIsSuspended = false; //So we don't execute this code again, //until a new suspend condition is detected. delay_count = 3600U; do { delay_count--; } while (delay_count); //Now drive the resume K-state signalling onto the USB bus. USBResumeControl = 1; // Start RESUME signaling delay_count = 1800U; // Set RESUME line for 1-13 ms do { delay_count--; } while (delay_count); USBResumeControl = 0; //Finished driving resume signalling USBUnmaskInterrupts(); } } }
/****************************************************************************** Function: void putUSBUSART(char *data, BYTE length) Summary: putUSBUSART writes an array of data to the USB. Use this version, is capable of transfering 0x00 (what is typically a NULL character in any of the string transfer functions). Description: putUSBUSART writes an array of data to the USB. Use this version, is capable of transfering 0x00 (what is typically a NULL character in any of the string transfer functions). Typical Usage: <code> if(USBUSARTIsTxTrfReady()) { char data[] = {0x00, 0x01, 0x02, 0x03, 0x04}; putUSBUSART(data,5); } </code> The transfer mechanism for device-to-host(put) is more flexible than host-to-device(get). It can handle a string of data larger than the maximum size of bulk IN endpoint. A state machine is used to transfer a \long string of data over multiple USB transactions. CDCTxService() must be called periodically to keep sending blocks of data to the host. Conditions: USBUSARTIsTxTrfReady() must return TRUE. This indicates that the last transfer is complete and is ready to receive a new block of data. The string of characters pointed to by 'data' must equal to or smaller than 255 BYTEs. Input: char *data - pointer to a RAM array of data to be transfered to the host BYTE length - the number of bytes to be transfered (must be less than 255). *****************************************************************************/ void putUSBUSART(char *data, BYTE length) { /* * User should have checked that cdc_trf_state is in CDC_TX_READY state * before calling this function. * As a safety precaution, this fuction checks the state one more time * to make sure it does not override any pending transactions. * * Currently it just quits the routine without reporting any errors back * to the user. * * Bottomline: User MUST make sure that USBUSARTIsTxTrfReady()==1 * before calling this function! * Example: * if(USBUSARTIsTxTrfReady()) * putUSBUSART(pData, Length); * * IMPORTANT: Never use the following blocking while loop to wait: * while(!USBUSARTIsTxTrfReady()) * putUSBUSART(pData, Length); * * The whole firmware framework is written based on cooperative * multi-tasking and a blocking code is not acceptable. * Use a state machine instead. */ USBMaskInterrupts(); if(cdc_trf_state == CDC_TX_READY) { mUSBUSARTTxRam((BYTE*)data, length); // See cdc.h } USBUnmaskInterrupts(); }//end putUSBUSART
uint16_t AsebaGetBuffer(AsebaVMState *vm, uint8_t * data, uint16_t maxLength, uint16_t* source) { int flags; uint16_t ret = 0; size_t u; // Touching the FIFO, mask the interrupt ... USBMaskInterrupts(flags); u = get_used(&AsebaUsb.rx); /* Minium packet size == len + src + msg_type == 6 bytes */ if(u >= 6) { int len; fifo_peek((unsigned char *) &len, &AsebaUsb.rx, 2); if (u >= len + 6) { memcpy_out_fifo((unsigned char *) &len, &AsebaUsb.rx, 2); memcpy_out_fifo((unsigned char *) source, &AsebaUsb.rx, 2); // msg_type is not in the len but is always present len = len + 2; /* Yay ! We have a complete packet ! */ if(len > maxLength) len = maxLength; memcpy_out_fifo(data, &AsebaUsb.rx, len); ret = len; } } if(usb_uart_serial_port_open()) USBCDCKickRx(); else fifo_reset(&AsebaUsb.rx); USBUnmaskInterrupts(flags); return ret; }
void USBCBSendResume(void){ static WORD delay_count; //should be checked). if(USBGetRemoteWakeupStatus() == TRUE){ if(USBIsBusSuspended() == TRUE){ USBMaskInterrupts(); //Clock switch to settings consistent with normal USB operation. USBCBWakeFromSuspend(); USBSuspendControl = 0; USBBusIsSuspended = FALSE; delay_count = 3600U; do{ delay_count--; }while(delay_count); //Now drive the resume K-state signalling onto the USB bus. USBResumeControl = 1; // Start RESUME signaling delay_count = 1800U; // Set RESUME line for 1-13 ms do{ delay_count--; }while(delay_count); USBResumeControl = 0; //Finished driving resume signalling USBUnmaskInterrupts(); } } }
/************************************************************************** Function: void putrsUSBUSART(const ROM char *data) Summary: putrsUSBUSART writes a string of data to the USB including the null character. Use this version, 'putrs', to transfer data literals and data located in program memory. Description: putrsUSBUSART writes a string of data to the USB including the null character. Use this version, 'putrs', to transfer data literals and data located in program memory. Typical Usage: <code> if(USBUSARTIsTxTrfReady()) { putrsUSBUSART("Hello World"); } </code> The transfer mechanism for device-to-host(put) is more flexible than host-to-device(get). It can handle a string of data larger than the maximum size of bulk IN endpoint. A state machine is used to transfer a \long string of data over multiple USB transactions. CDCTxService() must be called periodically to keep sending blocks of data to the host. Conditions: USBUSARTIsTxTrfReady() must return TRUE. This indicates that the last transfer is complete and is ready to receive a new block of data. The string of characters pointed to by 'data' must equal to or smaller than 255 BYTEs. Input: const ROM char *data - null\-terminated string of constant data. If a null character is not found, 255 BYTEs of data will be transferred to the host. **************************************************************************/ void putrsUSBUSART(const ROM char *data) { BYTE len; const ROM char *pData; /* * User should have checked that cdc_trf_state is in CDC_TX_READY state * before calling this function. * As a safety precaution, this fuction checks the state one more time * to make sure it does not override any pending transactions. * * Currently it just quits the routine without reporting any errors back * to the user. * * Bottomline: User MUST make sure that USBUSARTIsTxTrfReady() * before calling this function! * Example: * if(USBUSARTIsTxTrfReady()) * putsUSBUSART(pData); * * IMPORTANT: Never use the following blocking while loop to wait: * while(cdc_trf_state != CDC_TX_READY) * putsUSBUSART(pData); * * The whole firmware framework is written based on cooperative * multi-tasking and a blocking code is not acceptable. * Use a state machine instead. */ USBMaskInterrupts(); if(cdc_trf_state != CDC_TX_READY) { USBUnmaskInterrupts(); return; } /* * While loop counts the number of BYTEs to send including the * null character. */ len = 0; pData = data; do { len++; if(len == 255) break; // Break loop once max len is reached. }while(*pData++); /* * Second piece of information (length of data to send) is ready. * Call mUSBUSARTTxRom to setup the transfer. * The actual transfer process will be handled by CDCTxService(), * which should be called once per Main Program loop. */ mUSBUSARTTxRom((ROM BYTE*)data,len); // See cdc.h USBUnmaskInterrupts(); }//end putrsUSBUSART
void putcUSBUSART(char data) { USBMaskInterrupts(); if(cdc_trf_state == CDC_TX_READY) { mUSBUSARTTxRam((BYTE*)&data, 1); // See cdc.h } USBUnmaskInterrupts(); }
/******************************************************************** * Function: void USBCBSendResume(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: The USB specifications allow some types of USB * peripheral devices to wake up a host PC (such * as if it is in a low power suspend to RAM state). * This can be a very useful feature in some * USB applications, such as an Infrared remote * control receiver. If a user presses the "power" * button on a remote control, it is nice that the * IR receiver can detect this signalling, and then * send a USB "command" to the PC to wake up. * * The USBCBSendResume() "callback" function is used * to send this special USB signalling which wakes * up the PC. This function may be called by * application firmware to wake up the PC. This * function will only be able to wake up the host if * all of the below are true: * * 1. The USB driver used on the host PC supports * the remote wakeup capability. * 2. The USB configuration descriptor indicates * the device is remote wakeup capable in the * bmAttributes field. * 3. The USB host PC is currently sleeping, * and has previously sent your device a SET * FEATURE setup packet which "armed" the * remote wakeup capability. * * If the host has not armed the device to perform remote wakeup, * then this function will return without actually performing a * remote wakeup sequence. This is the required behavior, * as a USB device that has not been armed to perform remote * wakeup must not drive remote wakeup signalling onto the bus; * doing so will cause USB compliance testing failure. * * This callback should send a RESUME signal that * has the period of 1-15ms. * * Note: This function does nothing and returns quickly, if the USB * bus and host are not in a suspended condition, or are * otherwise not in a remote wakeup ready state. Therefore, it * is safe to optionally call this function regularly, ex: * anytime application stimulus occurs, as the function will * have no effect, until the bus really is in a state ready * to accept remote wakeup. * * When this function executes, it may perform clock switching, * depending upon the application specific code in * USBCBWakeFromSuspend(). This is needed, since the USB * bus will no longer be suspended by the time this function * returns. Therefore, the USB module will need to be ready * to receive traffic from the host. * * The modifiable section in this routine may be changed * to meet the application needs. Current implementation * temporary blocks other functions from executing for a * period of ~3-15 ms depending on the core frequency. * * According to USB 2.0 specification section 7.1.7.7, * "The remote wakeup device must hold the resume signaling * for at least 1 ms but for no more than 15 ms." * The idea here is to use a delay counter loop, using a * common value that would work over a wide range of core * frequencies. * That value selected is 1800. See table below: * ========================================================== * Core Freq(MHz) MIP RESUME Signal Period (ms) * ========================================================== * 48 12 1.05 * 4 1 12.6 * ========================================================== * * These timing could be incorrect when using code * optimization or extended instruction mode, * or when having other interrupts enabled. * Make sure to verify using the MPLAB SIM's Stopwatch * and verify the actual signal on an oscilloscope. *******************************************************************/ void USBCBSendResume(void) { static WORD delay_count; //First verify that the host has armed us to perform remote wakeup. //It does this by sending a SET_FEATURE request to enable remote wakeup, //usually just before the host goes to standby mode (note: it will only //send this SET_FEATURE request if the configuration descriptor declares //the device as remote wakeup capable, AND, if the feature is enabled //on the host (ex: on Windows based hosts, in the device manager //properties page for the USB device, power management tab, the //"Allow this device to bring the computer out of standby." checkbox //should be checked). if(USBGetRemoteWakeupStatus() == TRUE) { //Verify that the USB bus is in fact suspended, before we send //remote wakeup signalling. if(USBIsBusSuspended() == TRUE) { USBMaskInterrupts(); //Clock switch to settings consistent with normal USB operation. USBCBWakeFromSuspend(); USBSuspendControl = 0; USBBusIsSuspended = FALSE; //So we don't execute this code again, //until a new suspend condition is detected. //Section 7.1.7.7 of the USB 2.0 specifications indicates a USB //device must continuously see 5ms+ of idle on the bus, before it sends //remote wakeup signalling. One way to be certain that this parameter //gets met, is to add a 2ms+ blocking delay here (2ms plus at //least 3ms from bus idle to USBIsBusSuspended() == TRUE, yeilds //5ms+ total delay since start of idle). delay_count = 3600U; do { delay_count--; }while(delay_count); //Now drive the resume K-state signalling onto the USB bus. USBResumeControl = 1; // Start RESUME signaling delay_count = 1800U; // Set RESUME line for 1-13 ms do { delay_count--; }while(delay_count); USBResumeControl = 0; //Finished driving resume signalling USBUnmaskInterrupts(); } } }
void USBCBSendResume(void) { static WORD delay_count; if(USBGetRemoteWakeupStatus() == TRUE) { // Verify that the USB bus is in fact suspended, before we send // remote wakeup signalling. if(USBIsBusSuspended() == TRUE) { USBMaskInterrupts(); // Clock switch to settings consistent with normal USB operation. // USBCBWakeFromSuspend(); USBSuspendControl = 0; USBBusIsSuspended = FALSE; // So we don't execute this code again, // until a new suspend condition is // detected. // Section 7.1.7.7 of the USB 2.0 specifications indicates a USB // device must continuously see 5ms+ of idle on the bus, before it // sends remote wakeup signalling. One way to be certain that this // parameter gets met, is to add a 2ms+ blocking delay here // (2ms plus at least 3ms from bus idle to // USBIsBusSuspended() == TRUE, yeilds 5ms+ total delay since start // of idle). delay_count = 3600U; do { delay_count--; }while(delay_count); //Now drive the resume K-state signalling onto the USB bus. USBResumeControl = 1; // Start RESUME signaling delay_count = 1800U; // Set RESUME line for 1-13 ms do { delay_count--; }while(delay_count); USBResumeControl = 0; //Finished driving resume signalling USBUnmaskInterrupts(); } } }
// Send resume call-back void USBCBSendResume(void) { static WORD delay_count; // Verify that the host has armed us to perform remote wakeup. if(USBGetRemoteWakeupStatus() == FLAG_TRUE) { // Verify that the USB bus is suspended (before we send remote wakeup signalling). if(USBIsBusSuspended() == FLAG_TRUE) { USBMaskInterrupts(); // Bring the clock speed up to normal running state USBCBWakeFromSuspend(); USBSuspendControl = 0; USBBusIsSuspended = FLAG_FALSE; // Section 7.1.7.7 of the USB 2.0 specifications indicates a USB // device must continuously see 5ms+ of idle on the bus, before it sends // remote wakeup signalling. One way to be certain that this parameter // gets met, is to add a 2ms+ blocking delay here (2ms plus at // least 3ms from bus idle to USBIsBusSuspended() == FLAG_TRUE, yeilds // 5ms+ total delay since start of idle). delay_count = 3600U; do { delay_count--; } while(delay_count); // Start RESUME signaling for 1-13 ms USBResumeControl = 1; delay_count = 1800U; do { delay_count--; } while(delay_count); USBResumeControl = 0; USBUnmaskInterrupts(); } } }
void read_PSK1_HW_clock(unsigned int period, unsigned int ticks, BYTE *data, unsigned int bits, unsigned int timeout_us, unsigned int min_pulse_us) { // point globals at data for ISR EMU_Data= data; HW_Bits= bits; PSK_Min_Pulse= min_pulse_us; PSK_Read_Error= FALSE; memset(EMU_Data, '\0', bits); // stop USB interfering USBMaskInterrupts(); // start clock if not already running if(!mGetLED_Clock() == mLED_ON) { InitHWReaderClock(OC_TOGGLE_PULSE, period / 2L, period, RWD_STATE_ACTIVE); // give reader time to wake up and settle Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100); } // reset timer for timeout GetTimer_us(RESET); // align ourselves to reader's bit period by finding start of a pulse while(READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return; while(!READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return; // reset timer for external timeouts GetTimer_us(RESET); // start ISR to read PSK data InitHWReaderISR(CONVERT_TO_TICKS(period) * ticks - 1L, TRUE); }
void AsebaSendBuffer(AsebaVMState *vm, const uint8_t *data, uint16_t length) { int flags; // Here we must loop until we can send the data. // BUT if the usb connection is not available, we drop the packet if(!usb_uart_serial_port_open()) return; // Sanity check, should never be true if (length < 2) return; do { USBMaskInterrupts(flags); if(get_free(&AsebaUsb.tx) > length + 4) { length -= 2; memcpy_to_fifo(&AsebaUsb.tx, (unsigned char *) &length, 2); memcpy_to_fifo(&AsebaUsb.tx, (unsigned char *) &vm->nodeId, 2); memcpy_to_fifo(&AsebaUsb.tx, (unsigned char *) data, length + 2); // Will callback AsebaUsbTxReady if (!tx_busy) { tx_busy = 1; USBCDCKickTx(); } length = 0; } // Usb can be disconnected while sending ... if(!usb_uart_serial_port_open()) { fifo_reset(&AsebaUsb.tx); USBUnmaskInterrupts(flags); break; } USBUnmaskInterrupts(flags); } while(length); }
void CDCTxService(void) { BYTE byte_to_send; BYTE i; USBMaskInterrupts(); CDCNotificationHandler(); if(USBHandleBusy(CDCDataInHandle)) { USBUnmaskInterrupts(); return; } /* * Completing stage is necessary while [ mCDCUSartTxIsBusy()==1 ]. * By having this stage, user can always check cdc_trf_state, * and not having to call mCDCUsartTxIsBusy() directly. */ if(cdc_trf_state == CDC_TX_COMPLETING) cdc_trf_state = CDC_TX_READY; /* * If CDC_TX_READY state, nothing to do, just return. */ if(cdc_trf_state == CDC_TX_READY) { USBUnmaskInterrupts(); return; } /* * If CDC_TX_BUSY_ZLP state, send zero length packet */ if(cdc_trf_state == CDC_TX_BUSY_ZLP) { CDCDataInHandle = USBTxOnePacket(CDC_DATA_EP,NULL,0); //CDC_DATA_BD_IN.CNT = 0; cdc_trf_state = CDC_TX_COMPLETING; } else if(cdc_trf_state == CDC_TX_BUSY) { /* * First, have to figure out how many byte of data to send. */ if(cdc_tx_len > sizeof(cdc_data_tx)) byte_to_send = sizeof(cdc_data_tx); else byte_to_send = cdc_tx_len; /* * Subtract the number of bytes just about to be sent from the total. */ cdc_tx_len = cdc_tx_len - byte_to_send; pCDCDst.bRam = (BYTE*)&cdc_data_tx; // Set destination pointer i = byte_to_send; if(cdc_mem_type == USB_EP0_ROM) // Determine type of memory source { while(i) { *pCDCDst.bRam = *pCDCSrc.bRom; pCDCDst.bRam++; pCDCSrc.bRom++; i--; }//end while(byte_to_send) } else // _RAM { while(i) { *pCDCDst.bRam = *pCDCSrc.bRam; pCDCDst.bRam++; pCDCSrc.bRam++; i--; }//end while(byte_to_send._word) }//end if(cdc_mem_type...) /* * Lastly, determine if a zero length packet state is necessary. * See explanation in USB Specification 2.0: Section 5.8.3 */ if(cdc_tx_len == 0) { if(byte_to_send == CDC_DATA_IN_EP_SIZE) cdc_trf_state = CDC_TX_BUSY_ZLP; else cdc_trf_state = CDC_TX_COMPLETING; }//end if(cdc_tx_len...) CDCDataInHandle = USBTxOnePacket(CDC_DATA_EP,(BYTE*)&cdc_data_tx,byte_to_send); }//end if(cdc_tx_sate == CDC_TX_BUSY) USBUnmaskInterrupts(); }//end CDCTxService
void USBCCIDBulkInService(void) { WORD byte_to_send; BYTE i; USBMaskInterrupts(); if(USBHandleBusy(usbCcidBulkInHandle)) { USBUnmaskInterrupts(); return; } if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_COMPLETING) usbCcidBulkInTrfState = USB_CCID_BULK_IN_READY; /* * If USB_CCID_BULK_IN_READY state, nothing to do, just return. */ if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_READY) { USBUnmaskInterrupts(); return; } /* * If USB_CCID_BULK_IN_BUSY_ZLP state, send zero length packet */ if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_BUSY_ZLP) { usbCcidBulkInHandle = USBTxOnePacket(USB_EP_BULK_IN,NULL,0); usbCcidBulkInTrfState = USB_CCID_BULK_IN_COMPLETING; } else if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_BUSY) { /* * First, have to figure out how many byte of data to send. */ if(usbCcidBulkInLen > sizeof(usbCcidBulkInEndpoint)) byte_to_send = sizeof(usbCcidBulkInEndpoint); else byte_to_send = usbCcidBulkInLen; /* * Subtract the number of bytes just about to be sent from the total. */ usbCcidBulkInLen = usbCcidBulkInLen - byte_to_send; pCCIDDst.bRam = (BYTE*)usbCcidBulkInEndpoint; // Set destination pointer i = byte_to_send; while(i) { *pCCIDDst.bRam = *pCCIDSrc.bRam; pCCIDDst.bRam++; pCCIDSrc.bRam++; i--; }//end while(byte_to_send._word) /* * Lastly, determine if a zero length packet state is necessary. * See explanation in USB Specification 2.0: Section 5.8.3 */ if(usbCcidBulkInLen == 0) { if(byte_to_send == USB_EP_SIZE) usbCcidBulkInTrfState = USB_CCID_BULK_IN_BUSY_ZLP; else usbCcidBulkInTrfState = USB_CCID_BULK_IN_COMPLETING; }//end if(usbCcidBulkInLen...) usbCcidBulkInHandle = USBTxOnePacket(USB_EP_BULK_IN,(BYTE*)usbCcidBulkInEndpoint,byte_to_send); }//end if(cdc_tx_sate == USB_CCID_BULK_IN_BUSY) USBUnmaskInterrupts(); }//end USBCCIDBulkInService
// h/w clock reader - initialise data pointers for ISR and start timers // timer2 creates clock output for external reader // timer4 reads data bit values // period_us == clock for reader // ticks == clock periods per bit // bits == number of bits to read // oneshot must be set if we are reading data in response to RWD, so no repeating stream BOOL read_ASK_HW_clock(unsigned int period, unsigned int ticks, BYTE *data, unsigned int bits, unsigned int timeout_us, BOOL oneshot) { unsigned long dwell, time; BYTE count; Manchester_Error= FALSE; // if we're manchester or bi-phase encoding, we want to clock twice as fast so we can read both halves of the bit if(RFIDlerConfig.Manchester || RFIDlerConfig.BiPhase) { ticks /= 2; HW_Bits= (unsigned long) bits * 2; } else HW_Bits= (unsigned long) bits; // point globals at data for ISR EMU_Data= data; memset(EMU_Data, '\0', bits); // stop USB interfering USBMaskInterrupts(); // start clock if not already running if(!mGetLED_Clock() == mLED_ON) { InitHWReaderClock(OC_TOGGLE_PULSE, period / 2L, period, RWD_STATE_ACTIVE); // give reader time to wake up and settle Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100); } // align ourselves to reader's bit period by waiting until the end of a pulse GetTimer_us(RESET); count= READER_DATA; while(count == READER_DATA) if(GetTimer_us(NO_RESET) > timeout_us) return FALSE; // convert to ticks period= CONVERT_TO_TICKS(period); // biphase cannot auto-align when it detects a half-bit error, so we must align // on a full bit before we start if(!oneshot && RFIDlerConfig.BiPhase) { dwell= period * ticks * 2; count= 0; while((time= get_reader_gap(timeout_us))) { if(!time || count == 255) return; else if(approx(time, dwell, 10)) break; ++count; } } // wait for half the bit period so we sample mid-tick, not just as bit is toggling dwell= ((period * ticks) / 2L); GetTimer_ticks(RESET); //DEBUG_PIN_2= HIGH; while(GetTimer_ticks(NO_RESET) < dwell) ; // reset timer for external timeouts GetTimer_us(RESET); //DEBUG_PIN_2= LOW; // re-start reader ISR to read this bit if required InitHWReaderISR(period * ticks - 1L, TRUE); return TRUE; }
BOOL read_FSK_HW_clock(unsigned int period, unsigned int ticks, BYTE *data, unsigned int bits, unsigned int timeout_us) { unsigned int gaplength; // point globals at data for ISR EMU_Data= data; HW_Bits= bits; memset(EMU_Data, '\0', bits); // stop USB interfering USBMaskInterrupts(); // start clock if not already running if(!mGetLED_Clock() == mLED_ON) { InitHWReaderClock(OC_TOGGLE_PULSE, period / 2L, period, RWD_STATE_ACTIVE); // give reader time to wake up and settle Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100); } // reset timer for timeout GetTimer_us(RESET); // align ourselves to reader's bit period by finding the end of a pulse train. // we can do this by measuring the gaps. when they become significantly different // sized (more than 25%), we have just switched frequency. // find the start of a pulse while(READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; while(!READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; while(READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; // reset timer so we can meausure gap period GetTimer_us(RESET); while(!READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; gaplength= GetTimer_us(RESET); // now look for a gap that doesn't match while(42) { while(READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; GetTimer_us(TRUE); while(!READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; if(!approx(GetTimer_us(NO_RESET), gaplength, FSK_TOLERANCE)) break; } // reset timer for external timeouts GetTimer_us(RESET); // start ISR to read FSK data InitHWReaderISR(CONVERT_TO_TICKS(period) * ticks - 1L, TRUE); return TRUE; }