Table 1:
Example source code in C++ for software emulation of a delta-sigma EEG encoder that produces output compatible with the block diagram of the A-2000 DSP input stage shown in Figure 2A, with additional commentary. The code is written for clarity and expressive quality, rather than robustness or idiomatic succinctness.
| Example Routines for Emulation of an EEG Delta Sigma Encoder |
Commentary |
|---|---|
TIMER_CALLBACK_MEMBER(bis_state::updateDeltaSigmaEncoder)
{
double u[2];
uint32_t bitmask;
for (int ch = 0; ch < = 1; ch++) {
u[ch] = m_uPrev[ch] + (m_uNext[ch] - m_uPrev[ch])
* m_tic / 128;
m_sa[ch] = m_sa[ch] + u[ch] - m_v[ch];
m_sb[ch] = m_sb[ch] + u[ch] - m_v[ch];
bitmask = 1 << (ch + 5);
if (m_sb[ch] >= 0) {
m_v[ch] = 32767;
m_dsp_memory[0x820000] = ~bitmask;
} else {
m_v[ch] = −32768;
m_dsp_memory[0x820000] ∣= bitmask;
}
}
m_tic++;
if (m_tic > 128) m_tic = 128;
m_dsp->set_input_line(TMS3203X_IRQ1,ASSERT_LINE);
}
|
The routine updateDeltaSigmaEncoder is automatically called by a timer at rate of 16384 times per second, matching the EEG rate of 128 Hz oversampled 128 times. Variables beginning with m_ are class members. There are two EEG channels, numbered 0 and 1. Calculate u(t) by linearly interpolating values in time. Calculate the first delta sigma stage. (Figure 2A) Calculate the second delta sigma stage. (Figure 2A) Make a binary mask: bit 5 for channel 0, 6 for channel 1. Quantize based on the output from delta sigma stage 2. - Set v to the maximum possible value, +32767. - Clear the EEG signal input bit in the DSP memory map. OR - Set v to the minimum possible value, -32768. - Set the EEG signal input bit in the DSP memory map. Increase the oversample tic counter. There are 128 tics before new EEG values are obtained. Don’t let the tic counter go past 128, to prevent the linear interpolator from extrapolating outside of the available values. Raise interrupt request 1 on the DSP to trigger processing. |
TIMER_CALLBACK_MEMBER(bis_state::updateEEG) {
m_tic = 0;
for (int ch = 0; ch <= 1; ch++) {
m_uPrev[ch] = m_uNext[ch];
m_uNext[ch] = readNextScaledEEG();
}
}
|
The routine updateEEG is automatically called by a timer at a rate of 128 Hz, matching the EEG rate. The tic counter for the linear interpolation is reset. For each of the two channels, the next EEG value is moved to the previous EEG value, and a new EEG value is read in. |
double bis_state::readNextScaledEEG() {
uint8_t buffer[2];
double x = 0;
if (m_eegFileDevice->input(buffer,2) == 2) {
x = buffer[1] * 256 + buffer[0];
if (x >= 32768) x = x - 65536;
} return x;
}
|
The routine readNextScaledEEG loads in the next scaled EEG value from the input file (or any file-like datastream). Each scaled EEG value occupies two bytes. If two bytes cannot be read into a buffer (i.e. if the end of the file has been reached) then a value of zero is returned but, alternatively, one could exit the program as completed. The smaller byte is read first (i.e. little endian format). Values greater than +32767 actually represent negative values, and so need to be shifted accordingly. |