예제 #1
0
/**  Callback function which is called either from drvAPS_EM::pollerThread or from the interrupt driver when a pulse is received from the VME card.
  * Calls drvAPS_EM::readMeter and then drvQuadEM::computePositions.
  * \param[in] mask The mask of bit status in the Ip-Unidig. We can get callbacks on both high-to-low and low-to-high transitions
  * of the pulse to the digital I/O board.  We only want to use one or the other.
  * mask is 0 if this was a high-to-low transition, which is the one we use. 
  */
void drvAPS_EM::callbackFunc(epicsUInt32 mask)
{
    int input[QE_MAX_INPUTS];
    int i;
    static const char *functionName="intFunc";

    asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
              "%s:%s: got callback, mask=%x\n", driverName, functionName, mask);
    if (mask) return;
    lock();
    /* Read the new data */
    readMeter(input);
    if (readingsAveraged_ == 0) {
        for (i=0; i<QE_MAX_INPUTS; i++) {
            rawData_[i] = 0;
        }
    }
    for (i=0; i<QE_MAX_INPUTS; i++) {
        rawData_[i] += input[i];
    }
    readingsAveraged_++;
    if (readingsAveraged_ >= valuesPerRead_) {
        for (i=0; i<QE_MAX_INPUTS; i++) {
            rawData_[i] /= readingsAveraged_;
        }
        readingsAveraged_ = 0;
        /* Compute sum, difference, and position and do callbacks */
        computePositions(rawData_);
    }
    unlock();
}
예제 #2
0
void NORETURN chsTesting(void) {

	LOG_INFO(".:: CHs Testing\r\n");

	// Enabling all channels
	chEnabled = 0xFFFF;
	// Starting from CH[0]
	curCh = 0;

	while(1) {

		// Read power from ADE7753 meter
		readMeter(curCh);

		// Switch channel on Button push
		if (signal_pending(SIGNAL_PLAT_BUTTON) &&
				signal_status(SIGNAL_PLAT_BUTTON)) {
			curCh++;
			if (curCh>15)
				curCh=0;
			switchAnalogMux(curCh);
		}
	}

}
예제 #3
0
/** @brief Get a Power measure and return the measured channel */
static uint8_t sampleChannel(void) {
	uint16_t activeChs;

	// Get powered on (and enabled) channels
	activeChs = (getActiveChannels() & chEnabled & ~chSuspended);
	if (!activeChs)
		return MAX_CHANNELS;

	// If some _active_ channels are in fault mode: focus just on them only
	// This allows to reduce FAULTS DETECTION time perhaps also avoiding channel
	// switching
	if (chLossy &&
			(activeChs & chLossy)) {
		LOG_INFO("Lossy CHs [0x%02X]\r\n", chLossy);
		activeChs &= chLossy;
		// Remain on current channel if it is _active_ and _faulty_
		if (activeChs & BV16(curCh))
			goto sample;
		// Switch to the next _active_ abd _faulty_ channel
		goto select;
	}

	// If some _active_ channels are in calibration mode: focus just on them only
	// This allows to reduce CALIBRATION time perhaps also avoiding channel
	// switching
	if (!CalibrationDone() &&
			(activeChs & chCalib)) {
		DB2(LOG_INFO("Uncalibrated CHs [0x%02X]\r\n", chCalib));
		activeChs &= chCalib;
		// Remain on current channel if it is _active_ and _uncalibrated_
		if (activeChs & BV16(curCh))
			goto sample;
		// Switch to the next _active_ abd _uncalibrated_ channel
		goto select;
	}

select:

	// Select next active channel (max one single scan)
	// TODO optimize selection considering the board schematic
	for (uint8_t i = 0; i<MAX_CHANNELS; i++) {
		curCh++;
		if (curCh>15)
			curCh=0;
		if (BV16(curCh) & activeChs)
			break;
	}

	// Switch the analog MUX
	switchAnalogMux(curCh);

sample:

	// Read power from ADE7753 meter
	readMeter(curCh);

	return curCh;
}
예제 #4
0
static inline void switchAnalogMux(uint8_t ch) {
	// Set an invalid channel to force actual initialization at first call
	static uint8_t prevAmuxCh = 0xFF;
	uint8_t chSel;

	// Avoid unnecessary switch if channel has not changed
	if (ch == prevAmuxCh)
		return;

	prevAmuxCh = ch;
	chSel  = (0xF0 & PORTA);
	chSel |= chSelectionMap[ch];
	PORTA  = chSel;

	DB2(LOG_INFO("Switch Ch: %d => 0x%02X\r\n",
				ch, chSelectionMap[ch]));

	// Read one sample to trow away fauly ready from previous channel
	readMeter(ch);

}