/* Oximetry GUI Headers Copyright (c)2011 Mark Watkins License: GPL */ #ifndef OXIMETRY_H #define OXIMETRY_H #include #include #include #include #include #include "SleepLib/profiles.h" #include "SleepLib/day.h" #include "SleepLib/session.h" #include "Graphs/gLineChart.h" #include "Graphs/gFooBar.h" //! \brief Oximeters current mode enum SerialOxMode { SO_OFF, SO_IMPORT, SO_LIVE, SO_WAIT }; /*! \class SerialOximeter \author Mark Watkins \brief Base class for Serial Oximeters */ class SerialOximeter:public QObject { Q_OBJECT public: explicit SerialOximeter(QObject * parent,QString oxiname, QString portname="",BaudRateType baud=BAUD19200, FlowType flow=FLOW_OFF, ParityType parity=PAR_ODD, DataBitsType databits=DATA_8, StopBitsType stopbits=STOP_1); virtual ~SerialOximeter(); virtual void setSession(Session * sess) { session=sess; } //! \brief Open the serial port in either EventDriven or Polling mode virtual bool Open(QextSerialPort::QueryMode mode=QextSerialPort::EventDriven); //! \brief Close the serial port virtual void Close(); //! \brief Virtual method for Importing the Oximeters internal recording. virtual bool startImport()=0; //! \brief Virtual method to Abort importing the Oximeters internal recording. virtual void stopImport() {} // abort, default do nothing. //! \brief Start Serial "Live" Recording virtual bool startLive(); //! \brief Stop Serial "Live" Recording virtual void stopLive(); //! \brief Put the device in standard transmit mode virtual void resetDevice()=0; //! \brief Put the device in record request mode virtual void requestData()=0; //! \brief Return the current SerialOxMode, either SO_OFF, SO_IMPORT, SO_LIVE, SO_WAIT SerialOxMode mode() { return m_mode; } //! \brief Trash the session object void destroySession() { delete session; session=NULL; } //! \brief Returns true if the serial port is currently open bool isOpen() { return m_opened; } //! \brief Returns a count of callbacks, so a Timer can see the ports alive or dead. int callbacks() { return m_callbacks; } //! \brief Returns the time of the last callback in milliseconds since epoch qint64 lastTime() { return lasttime; } //! \brief Sets the time of the last callback in milliseconds since epoch void setLastTime(qint64 t) { lasttime=t; } //! \brief Return the current machine object Machine * getMachine() { return machine; } //! \brief Create a new Session object for the specified date Session *createSession(QDateTime date=QDateTime::currentDateTime()); //! \brief Returns the current session Session * getSession() { return session; } //! \brief Removes the TimeCodes, converting the EventList to Waveform type void compactToWaveform(EventList *el); //! \brief Packs EventList to time delta format, also pruning zeros. static void compactToEvent(EventList *el); //! \brief Packs SPO2 & Pulse to Events, and Plethy to Waveform EventList types. void compactAll(); //! \brief Sets the serial port device name void setPortName(QString portname); //! \brief Sets the serial ports Baud Rate (eg. BAUD19200, BAUD115200) void setBaudRate(BaudRateType baud); //! \brief Sets the serial ports Flow control to one of FLOW_OFF, FLOW_HARDWARE, or FLOW_XONXOFF void setFlowControl(FlowType flow); //! \brief Sets the serial ports Parity to one of PAR_NONE, PAR_ODD, PAR_EVEN, PAR_MARK (WINDOWS ONLY), PAR_SPACE void setParity(ParityType parity); //! \brief Sets the serial ports Data Bits to either DATA_5, DATA_6, DATA_7, or DATA_8 void setDataBits(DataBitsType databits); //! \brief Sets the serial ports Stop Bits to either STOP_1, STOP_1_5 (WINDOWS ONLY) or STOP_2 void setStopBits(StopBitsType stopbits); //! \brief Returns the serial port device name QString portName() { return m_portname; } //! \brief Returns the serial ports baud rate BaudRateType baudRate() { return m_baud; } //! \brief Returns the serial ports flow control setting FlowType flowControl() { return m_flow; } //! \brief Returns the serial ports parity setting ParityType parity() { return m_parity; } //! \brief Returns the serial ports data bits setting DataBitsType dataBits() { return m_databits; } //! \brief Returns the serial ports stop bits setting StopBitsType stopBits() { return m_stopbits; } EventList * Pulse() { return pulse; } EventList * Spo2() { return spo2; } EventList * Plethy() { return plethy; } virtual void addPulse(qint64 time, EventDataType pr); virtual void addSpO2(qint64 time, EventDataType o2); virtual void addPlethy(qint64 time, EventDataType pleth); signals: void sessionCreated(Session *); void dataChanged(); //! \brief This signal is called after import completion, to parse the event data. void importProcess(); //! \brief importProcess emits this signal after completion. void importComplete(Session *); //! \brief emitted when something goes wrong during import void importAborted(); //! \brief emitted to allow for UI updates to the progress bar void updateProgress(float f); // between 0 and 1. //! \brief emitted when live mode stops recording, passing the current Session void liveStopped(Session *); void updatePulse(float p); void updateSpO2(float p); protected slots: //! \brief Override this to process the serial import as it's received virtual void ReadyRead()=0; //! \brief Override this to parse the read import data virtual void import_process()=0; //! \brief This slot gets called when the serial port Times out virtual void Timeout(); //! \brief Override this to start the Import Timeout virtual void startImportTimeout()=0; protected: //virtual void addEvents(EventDataType pr, EventDataType o2, EventDataType pleth=-1000000); //! \brief Pointer to current session object Session * session; EventList * pulse; EventList * spo2; EventList * plethy; //! \brief Holds the serial port object QextSerialPort *m_port; SerialOxMode m_mode; bool m_opened; QString m_oxiname; QString m_portname; BaudRateType m_baud; FlowType m_flow; ParityType m_parity; DataBitsType m_databits; StopBitsType m_stopbits; QextSerialPort::QueryMode m_portmode; Machine *machine; qint64 lasttime; bool import_mode; int m_callbacks; bool done_import; QTimer *timer; EventDataType lasto2,lastpr; }; /*! \class CMS50Serial \author Mark Watkins \brief Serial Import & Live module */ class CMS50Serial:public SerialOximeter { public: explicit CMS50Serial(QObject * parent,QString portname); virtual ~CMS50Serial(); //! \brief Start the serial parts of Import mode. virtual bool startImport(); //! \brief Sends the 0xf6,0xf6,0xf6 data string to the serial port to start live mode again virtual void resetDevice(); //! \brief Sends the 0xf5, 0xf5 data string to request devices serial recording virtual void requestData(); protected: //! \brief CMS50 Time-out detection virtual void startImportTimeout(); //! \brief Called on completion of data import, to convert bytearray into event data virtual void import_process(); //! \brief Serial callback to process live view & store import data virtual void ReadyRead(); bool waitf6; short cntf6; short failcnt; QByteArray data; QVector f2time; int datasize; int received_bytes; int import_fails; QTime imptime; }; namespace Ui { class Oximetry; } enum PORTMODE { PM_LIVE, PM_RECORDING }; const int max_data_points=1000000; /*! \class Oximetry \author Mark Watkins \brief Oximetry view for working with Pulse Oximetry data and devices */ class Oximetry : public QWidget { Q_OBJECT public: explicit Oximetry(QWidget *parent, gGraphView * shared=NULL); ~Oximetry(); //! \brief Calls updateGL to redraw the graphs void RedrawGraphs(); //! \brief Returns the gGraphView object containing Oximetry graphs gGraphView *graphView() { return GraphView; } //! \brief Loads and displays a session containing oximetry data into into the Oximetry module void openSession(Session * session); private slots: //! \brief Scans the list of serial ports and detects any oximetry devices void on_RefreshPortsButton_clicked(); //! \brief Start or Stop live view mode void on_RunButton_toggled(bool checked); // Live mode button //! \brief This slot gets called when a new serial port is selected from the drop down void on_SerialPortsCombo_activated(const QString &arg1); //! \brief Start the Serial import process from the devices internal recordings void on_ImportButton_clicked(); //! \brief Asks to save oximetry session into SleepLib database void on_saveButton_clicked(); //! \brief Data has been changed, so it sets all the bits for live graph display void data_changed(); //! \brief Updates the Pulse Rate LCD widget when the live pulse changes void pulse_changed(float p); //! \brief Updates the SpO2 LCD widget when the live spO2 changes void spo2_changed(float o2); //! \brief Updates the progress bar during import void update_progress(float f); //! \brief Import failed, so cleanup. void import_aborted(); //! \brief Import completed, so get ready to display graphs void import_complete(Session *session); //! \brief Callback to make sure the oximeter is running void oximeter_running_check(); //! \brief Callback after liveView mode is stopped void live_stopped(Session *session); //! \brief Open button was clicked, so select and load .spo/.spoR data files void on_openButton_clicked(); //! \brief The datetime editor changed, so move the session data accordingly. void on_dateEdit_dateTimeChanged(const QDateTime &date); //! \brief Reset the datetime to what was set when first loaded void on_resetTimeButton_clicked(); private: //! \brief Imports a .spo file bool openSPOFile(QString filename); //! \brief Imports a .spoR file (from SPO2Review software in windows) bool openSPORFile(QString filename); //! \brief Clean up after import process, whether successful or not void import_finished(); //! \brief update the graphs to show the session information void updateGraphs(); Ui::Oximetry *ui; gGraphView *GraphView; MyScrollBar *scrollbar; QHBoxLayout *layout; gLineChart *pulse,*spo2,*plethy; Layer *lo1,*lo2; gGraph *PULSE,*SPO2,*PLETHY,*CONTROL; //! \brief Contains a list of gLineCharts that display Pulse, Plethy & SPO2 data QVector Data; QextSerialPort *port; QString portname; PORTMODE portmode; double lasttime,starttime; int lastpulse, lastspo2; Day * day; //Session * session; //EventList * ev_pulse; //EventList * ev_spo2; //EventList * ev_plethy; Layer * foobar; gGraphView * m_shared; SerialOximeter *oximeter; qint64 saved_starttime; bool firstSPO2Update; bool firstPulseUpdate; bool secondPulseUpdate; bool secondSPO2Update; bool dont_update_date; }; #endif // OXIMETRY_H