/** 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(); }
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); } } }
/** @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; }
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); }