Testing out the PPD42 Air Quality Sensor, with an MSP430 Launchpad and graphing the data with GNUplot.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

613 lines
17 KiB

/*-------------------------------------------------------------------------
| rxtx is a native interface to serial ports in java.
| Copyright 2002-2004 Michal Hobot MichalHobot@netscape.net
| Copyright 1997-2004 by Trent Jarvi taj@parcelfarce.linux.theplanet.co.uk
|
| This library is free software; you can redistribute it and/or
| modify it under the terms of the GNU Library General Public
| License as published by the Free Software Foundation; either
| version 2 of the License, or (at your option) any later version.
|
| This library is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
| Library General Public License for more details.
|
| You should have received a copy of the GNU Library General Public
| License along with this library; if not, write to the Free
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--------------------------------------------------------------------------*/
#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
#include "rxtxHelpers.h"
/*----------------------------------------------------------
get_java_int_var
accept: env (keyhole to java)
jobj (java RXTXPort object)
return: the jint field from the java object, casted to long
exceptions: none
comments:
----------------------------------------------------------*/
long get_java_int_var( JNIEnv *env, jobject jobj, char *id)
{
long result = 0;
jclass jclazz = env->GetObjectClass(jobj);
jfieldID jfd = env->GetFieldID(jclazz, id, "I");
if( !jfd ) {
IF_DEBUG
(
env->ExceptionDescribe();
)
env->ExceptionClear();
env->DeleteLocalRef(jclazz);
return result;
}
result = (long)( env->GetIntField(jobj, jfd) );
env->DeleteLocalRef(jclazz);
return result;
}
/*----------------------------------------------------------
get_java_boolean_var
accept: env (keyhole to java)
jobj (java RXTXPort object)
return: the jboolean field from the java object, converted to bool
exceptions: none
comments:
----------------------------------------------------------*/
bool get_java_boolean_var( JNIEnv *env, jobject jobj, char *id)
{
bool result = FALSE;
jclass jclazz = env->GetObjectClass(jobj);
jfieldID jfd = env->GetFieldID(jclazz, id, "Z");
if( !jfd ) {
IF_DEBUG
(
env->ExceptionDescribe();
)
env->ExceptionClear();
env->DeleteLocalRef(jclazz);
return result;
}
result = (env->GetBooleanField(jobj, jfd)) != JNI_FALSE;
env->DeleteLocalRef(jclazz);
return result;
}
/*----------------------------------------------------------
get_java_boolean_var2
accept: env (keyhole to java)
jobj (java RXTXPort object)
jclazz (class of jobj)
return: the jboolean field from the java object, converted to bool
exceptions: none
comments: can be faster for fetching many variables one by one
----------------------------------------------------------*/
bool get_java_boolean_var2(JNIEnv *env, jobject jobj, jclass jclazz, char *id)
{
bool result = FALSE;
jfieldID jfd = env->GetFieldID(jclazz, id, "Z");
if( !jfd ) {
IF_DEBUG
(
env->ExceptionDescribe();
)
env->ExceptionClear();
env->DeleteLocalRef(jclazz);
return result;
}
result = (env->GetBooleanField(jobj, jfd)) != JNI_FALSE;
return result;
}
/*----------------------------------------------------------
throw_java_exception
accept: env (keyhole to java)
*exc (exception class name)
*foo (function name)
*msg (error message)
perform: Throw a new java exception
return: none
exceptions: haha!
comments:
----------------------------------------------------------*/
void throw_java_exception(JNIEnv *env, const char *exc, const char *foo, const char *msg)
{
char buf[250];
jclass clazz = env->FindClass(exc);
if( !clazz ) {
IF_DEBUG
(
env->ExceptionDescribe();
)
env->ExceptionClear();
return;
}
_snprintf(buf, 60, "%s: %s in %s", exc, msg, foo);
env->ThrowNew(clazz, buf);
env->DeleteLocalRef(clazz);
}
// Unicode version:
void throw_java_exceptionW(JNIEnv *env, const char *exc, const wchar_t *foo, const wchar_t *msg)
{
wchar_t buf[500];
char *lpcBuf;
int msgLen;
jclass clazz = env->FindClass(exc);
if( !clazz ) {
env->ExceptionDescribe();
env->ExceptionClear();
return;
}
msgLen = swprintf(buf, L"%S: %s in %s", exc, msg, foo);
IF_DEBUG
(
printj(env, L"!!!!! Throwing %s\n", buf);
//MessageBox(NULL, buf, L"throw_java_exceptionW"), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
)
lpcBuf = (char *)malloc((msgLen+1)*sizeof(wchar_t)); // Will be ok - mbs not longer than wcs
lpcBuf[msgLen] = '\0';
wcstombs(lpcBuf, buf, msgLen);
env->ThrowNew(clazz, lpcBuf);
free(lpcBuf);
env->DeleteLocalRef(clazz);
}
/*----------------------------------------------------------
get_fd
accept: env (keyhole to java)
jobj (java RXTXPort object)
return: "fd" field from the java object, as HANDLE
exceptions: none
comments:
----------------------------------------------------------*/
HANDLE get_fd(JNIEnv *env, jobject jobj)
{
HANDLE fd = (HANDLE)get_java_int_var(env, jobj, "fd");
return fd!=0?fd:INVALID_HANDLE_VALUE;
}
/*----------------------------------------------------------
get_eis
accept: env (keyhole to java)
jobj (java RXTXPort object)
return: "eis" field from the java object, as (EventInfoStruct *)
exceptions: none
comments:
----------------------------------------------------------*/
EventInfoStruct *get_eis(JNIEnv *env, jobject jobj)
{
return (EventInfoStruct *)get_java_int_var(env, jobj, "eis");
}
/*----------------------------------------------------------
printj
accept: like vwprintf()
return: number of jchars written or -1
exceptions: none
comments: prints data using System.out.print()
----------------------------------------------------------*/
int printj(JNIEnv *env, wchar_t *fmt, ...)
{
wchar_t buf[1024];
int retval;
jstring jsBuf;
jclass clsSystem, clsOut;
jfieldID jfid;
jobject objOut;
jmethodID midPrint;
va_list ap;
va_start(ap, fmt);
retval = _vsnwprintf(buf, 1024, fmt, ap);
va_end(ap);
buf[1023] = '\0';
if((clsSystem = env->FindClass("java/lang/System")) == NULL)
{
IF_DEBUG
(
env->ExceptionDescribe();
)
env->ExceptionClear();
return -1;
}
if((jfid = env->GetStaticFieldID(clsSystem, "out", "Ljava/io/PrintStream;")) == NULL)
{
IF_DEBUG
(
env->ExceptionDescribe();
)
env->ExceptionClear();
env->DeleteLocalRef(clsSystem);
return -1;
}
objOut = env->GetStaticObjectField(clsSystem, jfid);
clsOut = env->GetObjectClass(objOut);
if((midPrint = env->GetMethodID(clsOut, "print", "(Ljava/lang/String;)V")) == NULL)
{
IF_DEBUG
(
env->ExceptionDescribe();
)
env->ExceptionClear();
env->DeleteLocalRef(clsOut);
env->DeleteLocalRef(clsSystem);
return -1;
}
jsBuf = env->NewString(buf, wcslen(buf));
env->CallVoidMethod(objOut, midPrint, jsBuf);
env->DeleteLocalRef(jsBuf);
env->DeleteLocalRef(clsOut);
env->DeleteLocalRef(clsSystem);
return retval;
}
/*----------------------------------------------------------
CommEventThread
accept: communication structure ptr
return: 0 - normal finish, other - error
exceptions: none
comments: runs as separate thread
----------------------------------------------------------*/
DWORD __stdcall CommEventThread(LPVOID lpEventInfo)
{
DWORD dwErr;
EventInfoStruct *EventInfo = (EventInfoStruct *)lpEventInfo;
HANDLE hPort = EventInfo->fd;
// Specify a set of events to be monitored for the port.
if(!SetCommMask(hPort, EventInfo->ef))
{
dwErr = GetLastError();
IF_DEBUG
(
LPCWSTR lpMsgBuf;
CreateErrorMsg(dwErr, lpMsgBuf);
MessageBoxW(NULL, lpMsgBuf, L"!!! CommEventThread - SetCommMask() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
ReleaseErrorMsg(lpMsgBuf);
)
return dwErr;
}
// Thread is ready to work
EventInfo->eventThreadReady = true;
do
{
// Wait for an event to occur for the port.
if(!WaitCommEvent(hPort, &(EventInfo->event), NULL))
{
dwErr = GetLastError();
if(dwErr == ERROR_INVALID_PARAMETER)
{ // Mask is empty - let's wait for a moment and continue
MessageBeep(MB_ICONQUESTION);
Sleep(200);
continue;
}
if(dwErr == ERROR_INVALID_HANDLE)
{ // Port was closed
//MessageBox(NULL, L"--- CommEventThread - Port closed", L"ERROR_INVALID_HANDLE", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
free(EventInfo);
return 0;
}
IF_DEBUG
(
LPCWSTR lpMsgBuf;
WCHAR MsgBuf2[1000];
CreateErrorMsg(dwErr, lpMsgBuf);
wsprintfW(MsgBuf2, L"%ld %s, CommMask==%ld", dwErr, lpMsgBuf, EventInfo->ef);
MessageBoxW(NULL, MsgBuf2, L"!!! CommEventThread - WaitCommEvent() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
ReleaseErrorMsg(lpMsgBuf);
)
return dwErr;
}
IF_DEBUG
(
MessageBeep(MB_ICONEXCLAMATION);
//MessageBoxW(NULL, L"--- RXTXPort.CommEventThread() - CommEvent", L"CommEventThread", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
)
// Re-specify the set of events to be monitored for the port.
if(!SetCommMask(hPort, EventInfo->ef))
{
dwErr = GetLastError();
IF_DEBUG
(
LPCWSTR lpMsgBuf;
CreateErrorMsg(dwErr, lpMsgBuf);
MessageBoxW(NULL, lpMsgBuf, L"!!! CommEventThread - SetCommMask() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
ReleaseErrorMsg(lpMsgBuf);
)
return dwErr;
}
if(!SetEvent(EventInfo->eventHandle))
{
dwErr = GetLastError();
if(dwErr == ERROR_INVALID_HANDLE) // Event was closed
{
//MessageBoxW(NULL, L"--- CommEventThread - Event closed", L"ERROR_INVALID_HANDLE", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
free(EventInfo);
return 0;
}
IF_DEBUG
(
LPCWSTR lpMsgBuf;
CreateErrorMsg(dwErr, lpMsgBuf);
MessageBoxW(NULL, lpMsgBuf, L"!!! CommEventThread - SetEvent() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
ReleaseErrorMsg(lpMsgBuf);
)
return dwErr;
}
// Wait for receiving and clearing event
while(EventInfo->event != 0)
Sleep(0);
} while(TRUE);
}
/*----------------------------------------------------------
setEventFlags
accept: EventFlag table
return: none
exceptions: none
comments: sets EventFlag table according to Java
MonitorThread fields
----------------------------------------------------------*/
/*void setEventFlags(JNIEnv *env, jobject jobjPort, bool ef[])
{
jfieldID jfid;
jclass cls;
jobject jobj;
jclass clsPort = env->GetObjectClass(jobjPort);
if((jfid = env->GetFieldID(clsPort, "monThread", "Lgnu/io/RXTXPort$MonitorThread;")) == NULL)
{
IF_DEBUG
(
env->ExceptionDescribe();
)
env->ExceptionClear();
env->DeleteLocalRef(clsPort);
return;
}
jobj = env->GetObjectField(jobjPort, jfid);
cls = env->GetObjectClass(jobj);
ef[SPE_DATA_AVAILABLE] = get_java_boolean_var2(env, jobj, cls, "Data");
ef[SPE_OUTPUT_BUFFER_EMPTY] = get_java_boolean_var2(env, jobj, cls, "Output");
ef[SPE_CTS] = get_java_boolean_var2(env, jobj, cls, "CTS");
ef[SPE_DSR] = get_java_boolean_var2(env, jobj, cls, "DSR");
ef[SPE_RI] = get_java_boolean_var2(env, jobj, cls, "RI");
ef[SPE_CD] = get_java_boolean_var2(env, jobj, cls, "CD");
ef[SPE_OE] = get_java_boolean_var2(env, jobj, cls, "OE");
ef[SPE_PE] = get_java_boolean_var2(env, jobj, cls, "PE");
ef[SPE_FE] = get_java_boolean_var2(env, jobj, cls, "FE");
ef[SPE_BI] = get_java_boolean_var2(env, jobj, cls, "BI");
env->DeleteLocalRef(clsPort);
env->DeleteLocalRef(cls);
env->DeleteLocalRef(jobj);
}
*/
/*----------------------------------------------------------
InitialiseEventInfoStruct
accept: Port handle
return: 0 - OK, other - error number
exceptions: none
comments: Structure for communication with thread
----------------------------------------------------------*/
int InitialiseEventInfoStruct(HANDLE hPort, EventInfoStruct **EventInfoPtr)
{
DWORD dwErr;
WCHAR wsEventName[MAX_PATH];
(*EventInfoPtr) = (EventInfoStruct *)malloc(sizeof(EventInfoStruct));
if(*EventInfoPtr == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
memset(*EventInfoPtr, 0, sizeof(EventInfoStruct));
(*EventInfoPtr)->fd = hPort;
wsprintfW(wsEventName, L"rxtxPort.SerEvt%lx", hPort);
(*EventInfoPtr)->eventHandle = CreateEventW(NULL, FALSE, FALSE, wsEventName);
dwErr = GetLastError();
if((*EventInfoPtr)->eventHandle == NULL || dwErr == ERROR_ALREADY_EXISTS)
{
IF_DEBUG
(
LPCWSTR lpMsgBuf;
CreateErrorMsg(dwErr, lpMsgBuf);
MessageBoxW(NULL, lpMsgBuf, L"!!! InitialiseEventInfoStruct - CreateEvent() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
ReleaseErrorMsg(lpMsgBuf);
)
free(*EventInfoPtr);
return dwErr;
}
// Set initial event flags: It should be not empty, but unused here and relatively rare event
(*EventInfoPtr)->ef = EV_POWER; //In WinNT you can use EV_EVENT2 instead
return 0;
}
/*----------------------------------------------------------
SendEvents
accept:
return:
exceptions: none
comments: Sends events needed
----------------------------------------------------------*/
int SendEvents(JNIEnv *env, jobject jobj, DWORD dwEvent, EventInfoStruct *EventInfo, jmethodID jmSendEvent)
{
DWORD dwErrors;
COMSTAT Stat;
IF_DEBUG
(
printj(env, L"--- SendEvents(): event %#lx\n", dwEvent);
)
if(!ClearCommError(EventInfo->fd, &dwErrors, &Stat))
{
IF_DEBUG
(
LPCWSTR lpMsgBuf;
CreateErrorMsg(GetLastError(), lpMsgBuf);
printj(env, L"!!! SendEvents - ClearCommError() error: %s\n", lpMsgBuf);
ReleaseErrorMsg(lpMsgBuf);
)
return -1;
}
// Ignore not subscribed events
dwEvent &= EventInfo->ef;
if(dwEvent & EV_RXCHAR)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): EV_RXCHAR\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_DATA_AVAILABLE, JNI_TRUE) == JNI_TRUE)
return SPE_DATA_AVAILABLE;
}
if(dwEvent & EV_TXEMPTY)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): EV_TXEMPTY\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_OUTPUT_BUFFER_EMPTY, JNI_TRUE) == JNI_TRUE)
return SPE_OUTPUT_BUFFER_EMPTY;
}
if(dwEvent & EV_CTS)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): EV_CTS\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_CTS, Stat.fCtsHold?JNI_TRUE:JNI_TRUE) == JNI_TRUE)
return SPE_CTS;
}
if(dwEvent & EV_DSR)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): EV_DSR\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_DSR, Stat.fDsrHold?JNI_TRUE:JNI_TRUE) == JNI_TRUE)
return SPE_DSR;
}
if(dwEvent & EV_RING)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): EV_RING\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_RI, JNI_TRUE) == JNI_TRUE)
return SPE_RI;
}
if(dwEvent & EV_RLSD)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): EV_RLSD\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_CD, Stat.fRlsdHold?JNI_TRUE:JNI_TRUE) == JNI_TRUE)
return SPE_CD;
}
if(dwEvent & EV_ERR)
{
if(dwErrors & CE_OVERRUN)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): CE_OVERRUN\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_OE, JNI_TRUE) == JNI_TRUE)
return SPE_OE;
}
if(dwErrors & CE_RXPARITY)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): CE_RXPARITY\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_PE, JNI_TRUE) == JNI_TRUE)
return SPE_PE;
}
if(dwErrors & CE_FRAME)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): CE_FRAME\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_FE, JNI_TRUE) == JNI_TRUE)
return SPE_FE;
}
}
if(dwEvent & EV_BREAK)
{
IF_DEBUG
(
printj(env, L"--- SendEvents(): EV_BREAK\n");
)
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_BI, JNI_TRUE) == JNI_TRUE)
return SPE_BI;
}
return 0;
}