#include<iostream>
#include<fstream>
#include<string>
#include<stdlib.h>
#include<list>
#include<vector>
using namespace std;
const short InTimeUnit = 1000; //1us 1000ns
const short OutTimeUnit = 200; //0.2us 200ns
typedef struct{
int Time; //time
float VoltPctDec; //value range: 0.0 ~ 1
}Point;
typedef struct {
float Interval; //time interval
float VoltPct; //value range:0~100
}SteadyLevel;
typedef struct{
float Down; //down interval
SteadyLevel Keep;
float Up; //Up interval
SteadyLevel Wait;
}Square;
//list<SquarePointsContainer> m_SquaPoinCntr;
//SquarePointsContainer
class WaveConv
{
public:
WaveConv(fstream &fIn);
void ReadLine(fstream &fIn);
bool ConvSquare(); //this func will discard the invalid Square
void WriteLine(fstream &fOut);
void ExtractSteadyLevel(string &Line, SteadyLevel &Level);
void LinearPoint(const Point &Start, const Point &End, list<Point> &PointLines);
//void AppendPoint(Point &p, list<string> &PointLines);
//void LinearSquare(Square &s, float DownVolt);
bool LinearSquare(Square &s, list<Point> &Points, int BaseTime = 0, float StartVolt = 100);
bool LinearSquare();//linear all the Squares to Points Containers,and store the Containers to SquarePointsContainers
void SpliceSquarePoints(const short *SquareOrder = NULL, int BaseTime = 0);
void LogSquares();
void LogPoints(list<Point> &p);
public:
vector<string> m_InLines;
list<Square> m_Squares;
vector<list<Point>> m_SquarePointsContainers;
list<Point> m_WavePoints;
list<string> m_OutLines;
};
WaveConv::WaveConv(fstream &fIn)
{
if(!fIn)
return;
ReadLine(fIn);
}
//void WaveConv::AppendPoint(Point &p, list<string> &Points)
//{
// char StrBuf[50];
// sprintf(StrBuf, "%d,%.2f", p.Time, p.VoltPctDec);
// string str(StrBuf);
// PointLines.push_back(str);
//}
void WaveConv::LinearPoint(const Point &Start, const Point &End, list<Point> &Points) {
//typedef struct{
// int Time; //time
// float VoltPctDec; //value range: 0.0 ~ 1
//}Point;
const Point *s = NULL;
const Point *e = NULL;
Start.Time < End.Time ? (s = &Start, e = &End) : (s = &End, e = &Start);
Point p;
float Slope = (e->VoltPctDec - s->VoltPctDec) / (e->Time - s->Time);
p.Time = s->Time;
while(p.Time < e->Time) {//excluding the End Point
p.VoltPctDec = (p.Time - s->Time) * Slope + s->VoltPctDec;
// cout << p.Time << "\t";
// cout << p.VoltPctDec << endl;
Points.push_back(p);
p.Time++;
}
}
//the default Voltage down from 100 percent
//the default BaseTime from 0
bool WaveConv::LinearSquare(Square &s, list<Point> &Points, int BaseTime, float StartVolt) {
const short InTimeUnit = 1000; //1us 1000ns
const short OutTimeUnit = 200; //0.2us 200ns
const short dec = 100;//convert to decimal value
int rate = InTimeUnit / OutTimeUnit;
Point Start, End;
//check whether the Square is valid
if(s.Down == 0 || s.Up == 0 || s.Keep.VoltPct == 100)
return false;
//down line
Start.Time = BaseTime;
End.Time = BaseTime + s.Down * rate;
Start.VoltPctDec = StartVolt / dec;
End.VoltPctDec = s.Keep.VoltPct / dec;
LinearPoint(Start, End, Points);
//keep line
memcpy(&Start, &End, sizeof(Start));
End.Time = Start.Time + s.Keep.Interval * rate;
LinearPoint(Start, End, Points);
//Up line
memcpy(&Start, &End, sizeof(Start));
End.Time = Start.Time + s.Up * rate;
End.VoltPctDec = s.Wait.VoltPct / dec;
LinearPoint(Start, End, Points);
//Wait line
memcpy(&Start, &End, sizeof(Start));
End.Time = Start.Time + s.Wait.Interval * rate;
LinearPoint(Start, End, Points);
return true;
}
bool WaveConv::LinearSquare()
{
if(!m_Squares.size())
return false;
list<Square>::iterator elem;
for(elem = m_Squares.begin(); elem != m_Squares.end(); elem++) {
list<Point> PointsContainer;
LinearSquare((*elem), PointsContainer);
m_SquarePointsContainers.push_back(PointsContainer);
}
}
void WaveConv::SpliceSquarePoints(const short *SquareOrder, int BaseTime)
{
const short *Order = NULL;
short n;
if((n = m_SquarePointsContainers.size()) == 0)
return;
if(SquareOrder == NULL){// splice the square in the normal order:0,1,2 ...
short *o = new short[n];
for(int i = 0; i < n; i++) //generate the normal order
*(o + i) = i;
Order = o;
}
else {
Order = SquareOrder;
}
for(int i = 0; i < n; i++)
{
if(Order[i] >= n)//the Square index in the order is invalid,and discard this index
continue;
list<Point> &sp = m_SquarePointsContainers[Order[i]];
Point p;
list<Point>::iterator elem;
for(elem = sp.begin(); elem != sp.end(); elem++) {
p.Time = BaseTime + (*elem).Time;
p.VoltPctDec = (*elem).VoltPctDec;
m_WavePoints.push_back(p);
}
BaseTime = p.Time + 1;
}
if(!SquareOrder)
delete[] Order;
}
void WaveConv::LogSquares()
{
list<Square>::iterator elem;
elem = m_Squares.begin();
while(elem != m_Squares.end()) {
cout << (*elem).Down << endl;
cout << (*elem).Keep.Interval << "\t";
cout << (*elem).Keep.VoltPct << endl;
cout << (*elem).Up << endl;
cout << (*elem).Wait.Interval << "\t";
cout << (*elem).Wait.VoltPct << endl;
cout << endl;
elem++;
}
}
void WaveConv::LogPoints(list<Point> &p)
{
list<Point>::iterator elem;
for(elem = p.begin(); elem != p.end(); elem++) {
cout << (*elem).Time << "\t";
cout << (*elem).VoltPctDec << endl;
}
}
void WaveConv::ReadLine(fstream &fIn)
{
m_InLines.clear();
string line;
while(getline(fIn, line))
{
if(line.empty())
continue;
m_InLines.push_back(line);
}
}
void WaveConv::ExtractSteadyLevel(string &Line, SteadyLevel &Level)
{
short CommaPos = Line.find(',');
string Sub;
Sub.assign(Line, 0, CommaPos);
Level.Interval = (float)atof(Sub.c_str());
Sub.assign(Line, CommaPos + 1, Line.size() - CommaPos - 1);
//cout << Sub << endl;
Level.VoltPct = (float)atof(Sub.c_str());
}
bool WaveConv::ConvSquare()
{
const short LineNumPerSquare = 4;
if(!m_InLines.size()) {
cout << "Err:ConvSquare():the inLine container is empty!!!" << endl;
return false;
}
if(m_InLines.size() % LineNumPerSquare != 0) {
cout << "Err:ConvSquare():the inLine container line num is invalid!!!" << endl;
return false;
}
int SquareNum = m_InLines.size() / LineNumPerSquare;
for(int i = 0; i < SquareNum; i++) {
Square s;
string &line = m_InLines[i * LineNumPerSquare];
s.Down = (float)atof(line.c_str());
line = m_InLines[i * LineNumPerSquare + 1];
ExtractSteadyLevel(line, s.Keep);
line = m_InLines[i * LineNumPerSquare + 2];
s.Up = (float)atof(line.c_str());
line = m_InLines[i * LineNumPerSquare + 3];
ExtractSteadyLevel(line, s.Wait);
if(s.Down == 0 || s.Up == 0 || s.Keep.VoltPct == 100) //discard the invalid Square
continue;
m_Squares.push_back(s);
}
return true;
}
int _tmain()
{
char InFileName[] = "./in.csv";
fstream fIn(InFileName);
if(fIn == NULL) {
cout << "Open Input failed!!!" << endl;
getchar();
return 0;
}
WaveConv Wave(fIn);
Wave.ConvSquare();
Wave.LinearSquare();
const short Order[] = {0, 1, 3, 2};
Wave.SpliceSquarePoints(Order);
Wave.LogPoints(Wave.m_WavePoints);
//vector<list<Point>>::iterator elem;
//for(elem = Wave.m_SquarePointsContainers.begin(); elem != Wave.m_SquarePointsContainers.end(); elem++)
//{
// cout << "------------------------\n";
// list<Point> &ps = *elem;
// Wave.LogPoints(ps);
// cout << endl;
//}
getchar();
}