added code to transmit sample frequency along with sample data (more compatibility between arduino and PC, and possibility to change sampling rate at run-time)
This commit is contained in:
parent
d0ef4ee9f9
commit
ef01fe74bb
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
// how many samples we want to skip between two samples we keep (can be used to lower the sampling frequency)
|
// how many samples we want to skip between two samples we keep (can be used to lower the sampling frequency)
|
||||||
#define SkipSamples 0
|
#define SkipSamples 0
|
||||||
|
byte regularEncodedFrequency;
|
||||||
|
|
||||||
const int BufferSize = 512;
|
const int BufferSize = 512;
|
||||||
byte buffer1[BufferSize];
|
byte buffer1[BufferSize];
|
||||||
@ -38,11 +39,19 @@ void setup()
|
|||||||
ADMUX |= (1 << REFS0); //set reference voltage
|
ADMUX |= (1 << REFS0); //set reference voltage
|
||||||
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
|
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
|
||||||
|
|
||||||
ADCSRA |= (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500KHz ; 13 cycles for a conversion which means 38000 samples per second
|
int ADPS = (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0);
|
||||||
|
ADCSRA |= ADPS; //set ADC clock with 32 prescaler- 16mHz/32=500KHz ; 13 cycles for a conversion which means 38000 samples per second
|
||||||
ADCSRA |= (1 << ADATE); //enabble auto trigger
|
ADCSRA |= (1 << ADATE); //enabble auto trigger
|
||||||
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
|
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
|
||||||
ADCSRA |= (1 << ADEN); //enable ADC
|
ADCSRA |= (1 << ADEN); //enable ADC
|
||||||
ADCSRA |= (1 << ADSC); //start ADC measurements
|
ADCSRA |= (1 << ADSC); //start ADC measurements
|
||||||
|
|
||||||
|
regularEncodedFrequency = (byte)ADPS;
|
||||||
|
byte skipSamples = 0;
|
||||||
|
#if SkipSamples > 0
|
||||||
|
skipSamples = SkipSamples;
|
||||||
|
#endif
|
||||||
|
regularEncodedFrequency |= skipSamples << 3;
|
||||||
|
|
||||||
sei();//enable interrupts
|
sei();//enable interrupts
|
||||||
|
|
||||||
@ -63,7 +72,9 @@ void loop()
|
|||||||
digitalWrite(LEDPin, LOW);
|
digitalWrite(LEDPin, LOW);
|
||||||
|
|
||||||
//Serial.write(currentBuffer, currentBufferSize);
|
//Serial.write(currentBuffer, currentBufferSize);
|
||||||
oscilloscope.write(currentBuffer, currentBufferSize, currentBufferStartTime);
|
oscilloscope.beginWrite(currentBufferSize + 1, currentBufferStartTime);
|
||||||
|
oscilloscope.continueWrite(®ularEncodedFrequency, 1);
|
||||||
|
oscilloscope.continueWrite(currentBuffer, currentBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
ISR(ADC_vect) {//when new ADC value ready
|
ISR(ADC_vect) {//when new ADC value ready
|
||||||
|
@ -23,16 +23,26 @@ SerialChannel::SerialChannel(const char* name_)
|
|||||||
|
|
||||||
void SerialChannel::write(byte* data, short byteCount, unsigned long time)
|
void SerialChannel::write(byte* data, short byteCount, unsigned long time)
|
||||||
{
|
{
|
||||||
if (time == (unsigned long)-1)
|
beginWrite(byteCount, time);
|
||||||
time = micros();
|
continueWrite(data, byteCount);
|
||||||
|
}
|
||||||
handleConnection();
|
|
||||||
|
|
||||||
Serial.write("START");
|
void SerialChannel::beginWrite(short byteCount, unsigned long time)
|
||||||
Serial.write(id);
|
{
|
||||||
writeULong(time);
|
if (time == (unsigned long)-1)
|
||||||
writeShort(byteCount);
|
time = micros();
|
||||||
Serial.write(data, byteCount);
|
|
||||||
|
handleConnection();
|
||||||
|
|
||||||
|
Serial.write("START");
|
||||||
|
Serial.write(id);
|
||||||
|
writeULong(time);
|
||||||
|
writeShort(byteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialChannel::continueWrite(byte* data, short byteCount)
|
||||||
|
{
|
||||||
|
Serial.write(data, byteCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialChannel::write(const char* text, unsigned long time)
|
void SerialChannel::write(const char* text, unsigned long time)
|
||||||
|
@ -17,6 +17,9 @@ public:
|
|||||||
void write(byte* data, short byteCount, unsigned long time = (unsigned long)-1);
|
void write(byte* data, short byteCount, unsigned long time = (unsigned long)-1);
|
||||||
|
|
||||||
void write(const char* text, unsigned long time = (unsigned long)-1);
|
void write(const char* text, unsigned long time = (unsigned long)-1);
|
||||||
|
|
||||||
|
void beginWrite(short byteCount, unsigned long time = (unsigned long)-1);
|
||||||
|
void continueWrite(byte* data, short byteCount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleConnection();
|
void handleConnection();
|
||||||
|
@ -85,7 +85,8 @@ namespace SerialMonitor
|
|||||||
MainWindowContext.Get.WriteLine(text);
|
MainWindowContext.Get.WriteLine(text);
|
||||||
break;
|
break;
|
||||||
case "oscilloscope":
|
case "oscilloscope":
|
||||||
MainWindowContext.Get.AddSequence(message.SendTime, message.Data);
|
byte frequency = message.Data[0];
|
||||||
|
MainWindowContext.Get.AddSequence(message.SendTime, frequency, message.Data.Skip(1).ToArray());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,13 @@ namespace SerialMonitor
|
|||||||
OnPropertyChanged("ConsoleText");
|
OnPropertyChanged("ConsoleText");
|
||||||
}
|
}
|
||||||
|
|
||||||
public double SampleDelay { get { return 0.000026; } }
|
|
||||||
public int MaxSequenceSize { get { return 2048; } }
|
public int MaxSequenceSize { get { return 2048; } }
|
||||||
|
|
||||||
private class Sequence
|
private class Sequence
|
||||||
{
|
{
|
||||||
public ulong StartTime { get; set; }
|
public ulong StartTime { get; set; } // time in microseconds of the first sample
|
||||||
public byte[] Data { get; set; }
|
public byte[] Data { get; set; }
|
||||||
|
public double Frequency { get; set; } // sampling rate (in samples per second)
|
||||||
|
|
||||||
public class Comparer : IComparer<Sequence>
|
public class Comparer : IComparer<Sequence>
|
||||||
{
|
{
|
||||||
@ -67,7 +67,8 @@ namespace SerialMonitor
|
|||||||
foreach (var sequence in Sequences)
|
foreach (var sequence in Sequences)
|
||||||
{
|
{
|
||||||
double seqStartTime = (double)sequence.StartTime/1000000.0;
|
double seqStartTime = (double)sequence.StartTime/1000000.0;
|
||||||
if (seqStartTime + (double)sequence.Data.Length * SampleDelay > ViewportStartTime && seqStartTime < ViewportStartTime + ViewportTimeWidth)
|
double sampleDelay = 1.0 / sequence.Frequency;
|
||||||
|
if (seqStartTime + (double)sequence.Data.Length * sampleDelay > ViewportStartTime && seqStartTime < ViewportStartTime + ViewportTimeWidth)
|
||||||
{
|
{
|
||||||
foreach (var line in ConvertToLines(sequence))
|
foreach (var line in ConvertToLines(sequence))
|
||||||
yield return line;
|
yield return line;
|
||||||
@ -82,6 +83,7 @@ namespace SerialMonitor
|
|||||||
double scale = viewportWidth / ViewportTimeWidth; // in pixels per second
|
double scale = viewportWidth / ViewportTimeWidth; // in pixels per second
|
||||||
|
|
||||||
ulong displayStartTime = (ulong)(viewportStartTime_ * 1000000.0);
|
ulong displayStartTime = (ulong)(viewportStartTime_ * 1000000.0);
|
||||||
|
double sampleDelay = 1.0 / sequence.Frequency;
|
||||||
|
|
||||||
double pos = ((double)sequence.StartTime - (double)displayStartTime) / 1000000.0 * scale;
|
double pos = ((double)sequence.StartTime - (double)displayStartTime) / 1000000.0 * scale;
|
||||||
if (pos > 1000)
|
if (pos > 1000)
|
||||||
@ -94,7 +96,7 @@ namespace SerialMonitor
|
|||||||
for (int idx = 1; idx < sequence.Data.Length; ++idx)
|
for (int idx = 1; idx < sequence.Data.Length; ++idx)
|
||||||
{
|
{
|
||||||
byte value = sequence.Data[idx];
|
byte value = sequence.Data[idx];
|
||||||
pos += SampleDelay * scale;
|
pos += sampleDelay * scale;
|
||||||
if (value > maxValue) maxValue = value;
|
if (value > maxValue) maxValue = value;
|
||||||
if (value < minValue) minValue = value;
|
if (value < minValue) minValue = value;
|
||||||
|
|
||||||
@ -110,7 +112,7 @@ namespace SerialMonitor
|
|||||||
prevPos = pos;
|
prevPos = pos;
|
||||||
line.X2 = pos;
|
line.X2 = pos;
|
||||||
|
|
||||||
double time = (double)sequence.StartTime / 1000000.0 + (double)idx * SampleDelay;
|
double time = (double)sequence.StartTime / 1000000.0 + (double)idx * sampleDelay;
|
||||||
double lastHeight = ValueToHeight(time, value);
|
double lastHeight = ValueToHeight(time, value);
|
||||||
|
|
||||||
if (idx == prevIdx + 1)
|
if (idx == prevIdx + 1)
|
||||||
@ -142,10 +144,20 @@ namespace SerialMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSequence(ulong startTime, byte[] data)
|
public void AddSequence(ulong startTime, byte frequency, byte[] data)
|
||||||
{
|
{
|
||||||
// TODO: merge sequences if total size is lower than MaxSequenceSize
|
// TODO: merge sequences if total size is lower than MaxSequenceSize
|
||||||
var sequence = new Sequence { StartTime = startTime, Data = data };
|
double cpuClock = 16000000.0;
|
||||||
|
int adsp0 = (frequency & (1 << 0)) != 0 ? 1 : 0;
|
||||||
|
int adsp1 = (frequency & (1 << 1)) != 0 ? 1 : 0;
|
||||||
|
int adsp2 = (frequency & (1 << 2)) != 0 ? 1 : 0;
|
||||||
|
int skipBit0 = (frequency & (1 << 3)) != 0 ? 1 : 0;
|
||||||
|
int skipBit1 = (frequency & (1 << 4)) != 0 ? 1 : 0;
|
||||||
|
int skipBit2 = (frequency & (1 << 5)) != 0 ? 1 : 0;
|
||||||
|
int adcDivider = 1 << Math.Max(1, adsp0 + adsp1*2 + adsp2*4);
|
||||||
|
int skip = skipBit0 + skipBit1 * 2 + skipBit2 * 4;
|
||||||
|
double freq = cpuClock / (double)adcDivider / 13.0 / (double)(1 + skip);
|
||||||
|
var sequence = new Sequence { StartTime = startTime, Frequency = freq, Data = data };
|
||||||
Sequences.Add(sequence);
|
Sequences.Add(sequence);
|
||||||
OnPropertyChanged("Oscilloscope");
|
OnPropertyChanged("Oscilloscope");
|
||||||
OnPropertyChanged("MinTime");
|
OnPropertyChanged("MinTime");
|
||||||
|
Loading…
Reference in New Issue
Block a user