From 0294b7ad95e32ff2031c3466ab601b1a4870cbd4 Mon Sep 17 00:00:00 2001 From: Koennecke Mark Date: Tue, 7 Jul 2015 12:33:02 +0200 Subject: [PATCH] Added the small support driver for the picoscope Added a deploysics script The Tcl data and time functions were moved to the SICS kernel --- make_gen | 2 +- pardef.c | 2 +- tclClock.c | 410 ----- tclDate.c | 1876 --------------------- tclUnixTime.c | 493 ------ utils/deploysics | 45 + utils/picoscope/Makefile | 17 + utils/picoscope/Makefile.osx | 17 + utils/picoscope/PS2000Acon.c | 2472 ++++++++++++++++++++++++++++ utils/picoscope/picocontrol | Bin 0 -> 15011 bytes utils/picoscope/picocontrol.c | 127 ++ utils/picoscope/picocontrol.plist | 41 + utils/picoscope/picocontrol.xinetd | 12 + utils/picoscope/picosig | Bin 0 -> 7585 bytes utils/picoscope/picosig.c | 69 + 15 files changed, 2802 insertions(+), 2781 deletions(-) delete mode 100644 tclClock.c delete mode 100644 tclDate.c delete mode 100644 tclUnixTime.c create mode 100755 utils/deploysics create mode 100644 utils/picoscope/Makefile create mode 100755 utils/picoscope/Makefile.osx create mode 100644 utils/picoscope/PS2000Acon.c create mode 100755 utils/picoscope/picocontrol create mode 100644 utils/picoscope/picocontrol.c create mode 100644 utils/picoscope/picocontrol.plist create mode 100755 utils/picoscope/picocontrol.xinetd create mode 100755 utils/picoscope/picosig create mode 100644 utils/picoscope/picosig.c diff --git a/make_gen b/make_gen index eaa40a6..23c2c52 100644 --- a/make_gen +++ b/make_gen @@ -24,7 +24,7 @@ OBJ=psi.o buffer.o ruli.o sps.o pimotor.o \ ritastorage.o poldizug.o el737hpdrivsps.o \ rebin.o sanslirebin.o lmd200.o slsvme.o julprot.o sinqhttpprot.o \ pfeifferprot.o termprot.o phytron.o autowin.o eigera2.o \ - tclClock.o tclDate.o tclUnixTime.o jvlprot.o \ + jvlprot.o \ eigermono.o sputterprot.o zwickroll.o astriumnet.o poldifold.o \ epicsadapter.o diff --git a/pardef.c b/pardef.c index 187b56f..006e590 100644 --- a/pardef.c +++ b/pardef.c @@ -387,7 +387,7 @@ static int ParOutError(SConnection * con, ParData * o) o->name, ctx->thisPar); break; case ILLNUM: - SCPrintf(con, eError, "ERROR: illegal value", o->name, ctx->valueArg); + SCPrintf(con, eError, "ERROR: illegal value %s %s", o->name, ctx->valueArg); break; case ILLARGC: SCPrintf(con, eError, "ERROR: illegal number of arguments for %s %s", diff --git a/tclClock.c b/tclClock.c deleted file mode 100644 index aca08db..0000000 --- a/tclClock.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * tclClock.c -- - * - * Contains the time and date related commands. This code - * is derived from the time and date facilities of TclX, - * by Mark Diekhans and Karl Lehenbauer. - * - * Copyright 1991-1995 Karl Lehenbauer and Mark Diekhans. - * Copyright (c) 1995 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclClock.c,v 1.1 2012/03/29 08:45:52 koennecke Exp $ - * - * Slightly modified for inclusion into SICS, Mark Koennecke, February 2012 - */ - -#include -#include - - - -#include - -typedef long TIMEZONE_t; -/* - * from tclDate.c - */ -int TclGetDate(char *p, Tcl_WideInt now, long zone, Tcl_WideInt *timePtr); -/* - * from tclUnixDate.c - */ -size_t TclpStrftime(char *s, size_t maxsize, CONST char *format, CONST struct tm *t, int useGMT); -struct tm * TclppGetDate(time_t time, int useGMT); - - -/* - * The date parsing stuff uses lexx and has tons o statics. - */ - -TCL_DECLARE_MUTEX(clockMutex) - -/* - * Function prototypes for local procedures in this file: - */ - -static int FormatClock _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_WideInt clockVal, int useGMT, - char *format)); - -/* - *------------------------------------------------------------------------- - * - * Tcl_ClockObjCmd -- - * - * This procedure is invoked to process the "clock" Tcl command. - * See the user documentation for details on what it does. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * See the user documentation. - * - *------------------------------------------------------------------------- - */ - -int -Tcl_ClockObjCmd (client, interp, objc, objv) - ClientData client; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ -{ - Tcl_Obj *resultPtr; - int index; - Tcl_Obj *CONST *objPtr; - int useGMT = 0; - char *format = "%a %b %d %X %Z %Y"; - int dummy; - Tcl_WideInt baseClock, clockVal; - long zone; - Tcl_Obj *baseObjPtr = NULL; - char *scanStr; - int n; - - static CONST char *switches[] = - {"clicks", "format", "scan", "seconds", (char *) NULL}; - enum command { COMMAND_CLICKS, COMMAND_FORMAT, COMMAND_SCAN, - COMMAND_SECONDS - }; - static CONST char *formatSwitches[] = {"-format", "-gmt", (char *) NULL}; - static CONST char *scanSwitches[] = {"-base", "-gmt", (char *) NULL}; - - resultPtr = Tcl_GetObjResult(interp); - if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); - return TCL_ERROR; - } - - if (Tcl_GetIndexFromObj(interp, objv[1], switches, "option", 0, &index) - != TCL_OK) { - return TCL_ERROR; - } - switch ((enum command) index) { - case COMMAND_CLICKS: { /* clicks */ - int forceMilli = 0; - - if (objc == 3) { - format = Tcl_GetStringFromObj(objv[2], &n); - if ( ( n >= 2 ) - && ( strncmp( format, "-milliseconds", - (unsigned int) n) == 0 ) ) { - forceMilli = 1; - } else { - Tcl_AppendStringsToObj(resultPtr, - "bad switch \"", format, - "\": must be -milliseconds", (char *) NULL); - return TCL_ERROR; - } - } else if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, "?-milliseconds?"); - return TCL_ERROR; - } - if (forceMilli) { - /* - * We can enforce at least millisecond granularity - */ - Tcl_Time time; - Tcl_GetTime(&time); - Tcl_SetLongObj(resultPtr, - (long) (time.sec*1000 + time.usec/1000)); - } else { - Tcl_SetLongObj(resultPtr, (long) TclpGetClicks()); - } - return TCL_OK; - } - - case COMMAND_FORMAT: /* format */ - if ((objc < 3) || (objc > 7)) { - wrongFmtArgs: - Tcl_WrongNumArgs(interp, 2, objv, - "clockval ?-format string? ?-gmt boolean?"); - return TCL_ERROR; - } - - if (Tcl_GetWideIntFromObj(interp, objv[2], &clockVal) - != TCL_OK) { - return TCL_ERROR; - } - - objPtr = objv+3; - objc -= 3; - while (objc > 1) { - if (Tcl_GetIndexFromObj(interp, objPtr[0], formatSwitches, - "switch", 0, &index) != TCL_OK) { - return TCL_ERROR; - } - switch (index) { - case 0: /* -format */ - format = Tcl_GetStringFromObj(objPtr[1], &dummy); - break; - case 1: /* -gmt */ - if (Tcl_GetBooleanFromObj(interp, objPtr[1], - &useGMT) != TCL_OK) { - return TCL_ERROR; - } - break; - } - objPtr += 2; - objc -= 2; - } - if (objc != 0) { - goto wrongFmtArgs; - } - return FormatClock(interp, clockVal, useGMT, - format); - - case COMMAND_SCAN: /* scan */ - if ((objc < 3) || (objc > 7)) { - wrongScanArgs: - Tcl_WrongNumArgs(interp, 2, objv, - "dateString ?-base clockValue? ?-gmt boolean?"); - return TCL_ERROR; - } - - objPtr = objv+3; - objc -= 3; - while (objc > 1) { - if (Tcl_GetIndexFromObj(interp, objPtr[0], scanSwitches, - "switch", 0, &index) != TCL_OK) { - return TCL_ERROR; - } - switch (index) { - case 0: /* -base */ - baseObjPtr = objPtr[1]; - break; - case 1: /* -gmt */ - if (Tcl_GetBooleanFromObj(interp, objPtr[1], - &useGMT) != TCL_OK) { - return TCL_ERROR; - } - break; - } - objPtr += 2; - objc -= 2; - } - if (objc != 0) { - goto wrongScanArgs; - } - - if (baseObjPtr != NULL) { - if (Tcl_GetWideIntFromObj(interp, baseObjPtr, - &baseClock) != TCL_OK) { - return TCL_ERROR; - } - } else { - baseClock = TclpGetSeconds(); - } - - if (useGMT) { - zone = -50000; /* Force GMT */ - } else { - zone = TclpGetTimeZone(baseClock); - } - - scanStr = Tcl_GetStringFromObj(objv[2], &dummy); - Tcl_MutexLock(&clockMutex); - if (TclGetDate(scanStr, baseClock, zone, - &clockVal) < 0) { - Tcl_MutexUnlock(&clockMutex); - Tcl_AppendStringsToObj(resultPtr, - "unable to convert date-time string \"", - scanStr, "\"", (char *) NULL); - return TCL_ERROR; - } - Tcl_MutexUnlock(&clockMutex); - - Tcl_SetWideIntObj(resultPtr, clockVal); - return TCL_OK; - - case COMMAND_SECONDS: /* seconds */ - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; - } - Tcl_SetLongObj(resultPtr, (long) TclpGetSeconds()); - return TCL_OK; - default: - return TCL_ERROR; /* Should never be reached. */ - } -} - -/* - *----------------------------------------------------------------------------- - * - * FormatClock -- - * - * Formats a time value based on seconds into a human readable - * string. - * - * Results: - * Standard Tcl result. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -static int -FormatClock(interp, clockVal, useGMT, format) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_WideInt clockVal; /* Time in seconds. */ - int useGMT; /* Boolean */ - char *format; /* Format string */ -{ - struct tm *timeDataPtr; - Tcl_DString buffer, uniBuffer; - int bufSize; - char *p; - int result; - time_t tclockVal; -#if !defined(HAVE_TM_ZONE) && !defined(WIN32) - TIMEZONE_t savedTimeZone = 0; /* lint. */ - char *savedTZEnv = NULL; /* lint. */ -#endif - -#ifdef HAVE_TZSET - /* - * Some systems forgot to call tzset in localtime, make sure its done. - */ - static int calledTzset = 0; - - Tcl_MutexLock(&clockMutex); - if (!calledTzset) { - tzset(); - calledTzset = 1; - } - Tcl_MutexUnlock(&clockMutex); -#endif - - /* - * If the user gave us -format "", just return now - */ - if (*format == '\0') { - return TCL_OK; - } - -#if !defined(HAVE_TM_ZONE) && !defined(WIN32) - /* - * This is a kludge for systems not having the timezone string in - * struct tm. No matter what was specified, they use the local - * timezone string. Since this kludge requires fiddling with the - * TZ environment variable, it will mess up if done on multiple - * threads at once. Protect it with a the clock mutex. - */ - - Tcl_MutexLock( &clockMutex ); - if (useGMT) { - CONST char *varValue; - - varValue = Tcl_GetVar2(interp, "env", "TZ", TCL_GLOBAL_ONLY); - if (varValue != NULL) { - savedTZEnv = strcpy(ckalloc(strlen(varValue) + 1), varValue); - } else { - savedTZEnv = NULL; - } - Tcl_SetVar2(interp, "env", "TZ", "GMT0", TCL_GLOBAL_ONLY); - savedTimeZone = timezone; - timezone = 0; - tzset(); - } -#endif - - tclockVal = (time_t) clockVal; - timeDataPtr = TclppGetDate(tclockVal, useGMT); - - /* - * Make a guess at the upper limit on the substituted string size - * based on the number of percents in the string. - */ - - for (bufSize = 1, p = format; *p != '\0'; p++) { - if (*p == '%') { - bufSize += 40; - if (p[1] == 'c') { - bufSize += 226; - } - } else { - bufSize++; - } - } - Tcl_DStringInit(&uniBuffer); - Tcl_UtfToExternalDString(NULL, format, -1, &uniBuffer); - Tcl_DStringInit(&buffer); - Tcl_DStringSetLength(&buffer, bufSize); - - /* If we haven't locked the clock mutex up above, lock it now. */ - -#if defined(HAVE_TM_ZONE) || defined(WIN32) - Tcl_MutexLock(&clockMutex); -#endif - result = TclpStrftime(buffer.string, (unsigned int) bufSize, - Tcl_DStringValue(&uniBuffer), timeDataPtr, useGMT); -#if defined(HAVE_TM_ZONE) || defined(WIN32) - Tcl_MutexUnlock(&clockMutex); -#endif - Tcl_DStringFree(&uniBuffer); - -#if !defined(HAVE_TM_ZONE) && !defined(WIN32) - if (useGMT) { - if (savedTZEnv != NULL) { - Tcl_SetVar2(interp, "env", "TZ", savedTZEnv, TCL_GLOBAL_ONLY); - ckfree(savedTZEnv); - } else { - Tcl_UnsetVar2(interp, "env", "TZ", TCL_GLOBAL_ONLY); - } - timezone = savedTimeZone; - tzset(); - } - Tcl_MutexUnlock( &clockMutex ); -#endif - - if (result == 0) { - /* - * A zero return is the error case (can also mean the strftime - * didn't get enough space to write into). We know it doesn't - * mean that we wrote zero chars because the check for an empty - * format string is above. - */ - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad format string \"", format, "\"", (char *) NULL); - return TCL_ERROR; - } - - /* - * Convert the time to UTF from external encoding [Bug: 3345] - */ - Tcl_DStringInit(&uniBuffer); - Tcl_ExternalToUtfDString(NULL, buffer.string, -1, &uniBuffer); - - Tcl_SetStringObj(Tcl_GetObjResult(interp), uniBuffer.string, -1); - - Tcl_DStringFree(&uniBuffer); - Tcl_DStringFree(&buffer); - return TCL_OK; -} - diff --git a/tclDate.c b/tclDate.c deleted file mode 100644 index 6abca44..0000000 --- a/tclDate.c +++ /dev/null @@ -1,1876 +0,0 @@ -/* - * tclDate.c -- - * - * This file is generated from a yacc grammar defined in - * the file tclGetDate.y. It should not be edited directly. - * - * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans. - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclDate.c,v 1.1 2012/03/29 08:45:52 koennecke Exp $ - */ - -#include -#include -#include - -#if defined(MAC_TCL) && !defined(TCL_MAC_USE_MSL_EPOCH) -# define EPOCH 1904 -# define START_OF_TIME 1904 -# define END_OF_TIME 2039 -#else -# define EPOCH 1970 -# define START_OF_TIME 1902 -# define END_OF_TIME 2037 -#endif - -/* - * The offset of tm_year of struct tm returned by localtime, gmtime, etc. - * I don't know how universal this is; K&R II, the NetBSD manpages, and - * ../compat/strftime.c all agree that tm_year is the year-1900. However, - * some systems may have a different value. This #define should be the - * same as in ../compat/strftime.c. - */ -#define TM_YEAR_BASE 1900 - -#define HOUR(x) ((int) (60 * x)) -#define SECSPERDAY (24L * 60L * 60L) -#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) - -/* - * An entry in the lexical lookup table. - */ -typedef struct _TABLE { - char *name; - int type; - time_t value; -} TABLE; - - -/* - * Daylight-savings mode: on, off, or not yet known. - */ -typedef enum _DSTMODE { - DSTon, DSToff, DSTmaybe -} DSTMODE; - -/* - * Meridian: am, pm, or 24-hour style. - */ -typedef enum _MERIDIAN { - MERam, MERpm, MER24 -} MERIDIAN; - - -/* - * Global variables. We could get rid of most of these by using a good - * union as the yacc stack. (This routine was originally written before - * yacc had the %union construct.) Maybe someday; right now we only use - * the %union very rarely. - */ -static char *TclDateInput; -static DSTMODE TclDateDSTmode; -static time_t TclDateDayOrdinal; -static time_t TclDateDayNumber; -static time_t TclDateMonthOrdinal; -static int TclDateHaveDate; -static int TclDateHaveDay; -static int TclDateHaveOrdinalMonth; -static int TclDateHaveRel; -static int TclDateHaveTime; -static int TclDateHaveZone; -static time_t TclDateTimezone; -static time_t TclDateDay; -static time_t TclDateHour; -static time_t TclDateMinutes; -static time_t TclDateMonth; -static time_t TclDateSeconds; -static time_t TclDateYear; -static MERIDIAN TclDateMeridian; -static time_t TclDateRelMonth; -static time_t TclDateRelDay; -static time_t TclDateRelSeconds; -static time_t *TclDateRelPointer; - -/* - * Prototypes of internal functions. - */ -static void TclDateerror _ANSI_ARGS_((char *s)); -static time_t ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes, - time_t Seconds, MERIDIAN Meridian)); -static int Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year, - time_t Hours, time_t Minutes, time_t Seconds, - MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr)); -static time_t DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future)); -static time_t NamedDay _ANSI_ARGS_((time_t Start, time_t DayOrdinal, - time_t DayNumber)); -static time_t NamedMonth _ANSI_ARGS_((time_t Start, time_t MonthOrdinal, - time_t MonthNumber)); -static int RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth, - time_t *TimePtr)); -static int RelativeDay _ANSI_ARGS_((time_t Start, time_t RelDay, - time_t *TimePtr)); -static int LookupWord _ANSI_ARGS_((char *buff)); -static int TclDatelex _ANSI_ARGS_((void)); - -int -TclDateparse _ANSI_ARGS_((void)); -typedef union -#ifdef __cplusplus - YYSTYPE -#endif - { - time_t Number; - enum _MERIDIAN Meridian; -} YYSTYPE; -# define tAGO 257 -# define tDAY 258 -# define tDAYZONE 259 -# define tID 260 -# define tMERIDIAN 261 -# define tMINUTE_UNIT 262 -# define tMONTH 263 -# define tMONTH_UNIT 264 -# define tSTARDATE 265 -# define tSEC_UNIT 266 -# define tSNUMBER 267 -# define tUNUMBER 268 -# define tZONE 269 -# define tEPOCH 270 -# define tDST 271 -# define tISOBASE 272 -# define tDAY_UNIT 273 -# define tNEXT 274 - - - - -#if defined(__cplusplus) || defined(__STDC__) - -#if defined(__cplusplus) && defined(__EXTERN_C__) -extern "C" { -#endif -#ifndef TclDateerror -#if defined(__cplusplus) - void TclDateerror(CONST char *); -#endif -#endif -#ifndef TclDatelex - int TclDatelex(void); -#endif - int TclDateparse(void); -#if defined(__cplusplus) && defined(__EXTERN_C__) -} -#endif - -#endif - -#define TclDateclearin TclDatechar = -1 -#define TclDateerrok TclDateerrflag = 0 -extern int TclDatechar; -extern int TclDateerrflag; -YYSTYPE TclDatelval; -YYSTYPE TclDateval; -typedef int TclDatetabelem; -#ifndef YYMAXDEPTH -#define YYMAXDEPTH 150 -#endif -#if YYMAXDEPTH > 0 -int TclDate_TclDates[YYMAXDEPTH], *TclDates = TclDate_TclDates; -YYSTYPE TclDate_TclDatev[YYMAXDEPTH], *TclDatev = TclDate_TclDatev; -#else /* user does initial allocation */ -int *TclDates; -YYSTYPE *TclDatev; -#endif -static int TclDatemaxdepth = YYMAXDEPTH; -# define YYERRCODE 256 - - -/* - * Month and day table. - */ -static TABLE MonthDayTable[] = { - { "january", tMONTH, 1 }, - { "february", tMONTH, 2 }, - { "march", tMONTH, 3 }, - { "april", tMONTH, 4 }, - { "may", tMONTH, 5 }, - { "june", tMONTH, 6 }, - { "july", tMONTH, 7 }, - { "august", tMONTH, 8 }, - { "september", tMONTH, 9 }, - { "sept", tMONTH, 9 }, - { "october", tMONTH, 10 }, - { "november", tMONTH, 11 }, - { "december", tMONTH, 12 }, - { "sunday", tDAY, 0 }, - { "monday", tDAY, 1 }, - { "tuesday", tDAY, 2 }, - { "tues", tDAY, 2 }, - { "wednesday", tDAY, 3 }, - { "wednes", tDAY, 3 }, - { "thursday", tDAY, 4 }, - { "thur", tDAY, 4 }, - { "thurs", tDAY, 4 }, - { "friday", tDAY, 5 }, - { "saturday", tDAY, 6 }, - { NULL } -}; - -/* - * Time units table. - */ -static TABLE UnitsTable[] = { - { "year", tMONTH_UNIT, 12 }, - { "month", tMONTH_UNIT, 1 }, - { "fortnight", tDAY_UNIT, 14 }, - { "week", tDAY_UNIT, 7 }, - { "day", tDAY_UNIT, 1 }, - { "hour", tSEC_UNIT, 60 * 60 }, - { "minute", tSEC_UNIT, 60 }, - { "min", tSEC_UNIT, 60 }, - { "second", tSEC_UNIT, 1 }, - { "sec", tSEC_UNIT, 1 }, - { NULL } -}; - -/* - * Assorted relative-time words. - */ -static TABLE OtherTable[] = { - { "tomorrow", tDAY_UNIT, 1 }, - { "yesterday", tDAY_UNIT, -1 }, - { "today", tDAY_UNIT, 0 }, - { "now", tSEC_UNIT, 0 }, - { "last", tUNUMBER, -1 }, - { "this", tSEC_UNIT, 0 }, - { "next", tNEXT, 1 }, -#if 0 - { "first", tUNUMBER, 1 }, - { "second", tUNUMBER, 2 }, - { "third", tUNUMBER, 3 }, - { "fourth", tUNUMBER, 4 }, - { "fifth", tUNUMBER, 5 }, - { "sixth", tUNUMBER, 6 }, - { "seventh", tUNUMBER, 7 }, - { "eighth", tUNUMBER, 8 }, - { "ninth", tUNUMBER, 9 }, - { "tenth", tUNUMBER, 10 }, - { "eleventh", tUNUMBER, 11 }, - { "twelfth", tUNUMBER, 12 }, -#endif - { "ago", tAGO, 1 }, - { "epoch", tEPOCH, 0 }, - { "stardate", tSTARDATE, 0}, - { NULL } -}; - -/* - * The timezone table. (Note: This table was modified to not use any floating - * point constants to work around an SGI compiler bug). - */ -static TABLE TimezoneTable[] = { - { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */ - { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */ - { "utc", tZONE, HOUR( 0) }, - { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */ - { "wet", tZONE, HOUR( 0) }, /* Western European */ - { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */ - { "wat", tZONE, HOUR( 1) }, /* West Africa */ - { "at", tZONE, HOUR( 2) }, /* Azores */ -#if 0 - /* For completeness. BST is also British Summer, and GST is - * also Guam Standard. */ - { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */ - { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */ -#endif - { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */ - { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */ - { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */ - { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */ - { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */ - { "est", tZONE, HOUR( 5) }, /* Eastern Standard */ - { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */ - { "cst", tZONE, HOUR( 6) }, /* Central Standard */ - { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */ - { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */ - { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */ - { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */ - { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */ - { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */ - { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */ - { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */ - { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */ - { "cat", tZONE, HOUR(10) }, /* Central Alaska */ - { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */ - { "nt", tZONE, HOUR(11) }, /* Nome */ - { "idlw", tZONE, HOUR(12) }, /* International Date Line West */ - { "cet", tZONE, -HOUR( 1) }, /* Central European */ - { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */ - { "met", tZONE, -HOUR( 1) }, /* Middle European */ - { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */ - { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */ - { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */ - { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */ - { "fwt", tZONE, -HOUR( 1) }, /* French Winter */ - { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */ - { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */ - { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */ - { "it", tZONE, -HOUR( 7/2) }, /* Iran */ - { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */ - { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */ - { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */ - { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */ -#if 0 - /* For completeness. NST is also Newfoundland Stanard, nad SST is - * also Swedish Summer. */ - { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */ - { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */ -#endif /* 0 */ - { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */ - { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */ - { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */ - { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */ - { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */ - { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */ - { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */ - { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */ - { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */ - { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */ - { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */ - { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */ - { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */ - { "nzt", tZONE, -HOUR(12) }, /* New Zealand */ - { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */ - { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */ - { "idle", tZONE, -HOUR(12) }, /* International Date Line East */ - /* ADDED BY Marco Nijdam */ - { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */ - /* End ADDED */ - { NULL } -}; - -/* - * Military timezone table. - */ -static TABLE MilitaryTable[] = { - { "a", tZONE, HOUR( 1) }, - { "b", tZONE, HOUR( 2) }, - { "c", tZONE, HOUR( 3) }, - { "d", tZONE, HOUR( 4) }, - { "e", tZONE, HOUR( 5) }, - { "f", tZONE, HOUR( 6) }, - { "g", tZONE, HOUR( 7) }, - { "h", tZONE, HOUR( 8) }, - { "i", tZONE, HOUR( 9) }, - { "k", tZONE, HOUR( 10) }, - { "l", tZONE, HOUR( 11) }, - { "m", tZONE, HOUR( 12) }, - { "n", tZONE, HOUR(- 1) }, - { "o", tZONE, HOUR(- 2) }, - { "p", tZONE, HOUR(- 3) }, - { "q", tZONE, HOUR(- 4) }, - { "r", tZONE, HOUR(- 5) }, - { "s", tZONE, HOUR(- 6) }, - { "t", tZONE, HOUR(- 7) }, - { "u", tZONE, HOUR(- 8) }, - { "v", tZONE, HOUR(- 9) }, - { "w", tZONE, HOUR(-10) }, - { "x", tZONE, HOUR(-11) }, - { "y", tZONE, HOUR(-12) }, - { "z", tZONE, HOUR( 0) }, - { NULL } -}; - - -/* - * Dump error messages in the bit bucket. - */ -static void -TclDateerror(s) - char *s; -{ -} - - -static time_t -ToSeconds(Hours, Minutes, Seconds, Meridian) - time_t Hours; - time_t Minutes; - time_t Seconds; - MERIDIAN Meridian; -{ - if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) - return -1; - switch (Meridian) { - case MER24: - if (Hours < 0 || Hours > 23) - return -1; - return (Hours * 60L + Minutes) * 60L + Seconds; - case MERam: - if (Hours < 1 || Hours > 12) - return -1; - return ((Hours % 12) * 60L + Minutes) * 60L + Seconds; - case MERpm: - if (Hours < 1 || Hours > 12) - return -1; - return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds; - } - return -1; /* Should never be reached */ -} - -/* - *----------------------------------------------------------------------------- - * - * Convert -- - * - * Convert a {month, day, year, hours, minutes, seconds, meridian, dst} - * tuple into a clock seconds value. - * - * Results: - * 0 or -1 indicating success or failure. - * - * Side effects: - * Fills TimePtr with the computed value. - * - *----------------------------------------------------------------------------- - */ -static int -Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr) - time_t Month; - time_t Day; - time_t Year; - time_t Hours; - time_t Minutes; - time_t Seconds; - MERIDIAN Meridian; - DSTMODE DSTmode; - time_t *TimePtr; -{ - static int DaysInMonth[12] = { - 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - time_t tod; - time_t Julian; - int i; - - /* Figure out how many days are in February for the given year. - * Every year divisible by 4 is a leap year. - * But, every year divisible by 100 is not a leap year. - * But, every year divisible by 400 is a leap year after all. - */ - DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28; - - /* Check the inputs for validity */ - if (Month < 1 || Month > 12 - || Year < START_OF_TIME || Year > END_OF_TIME - || Day < 1 || Day > DaysInMonth[(int)--Month]) - return -1; - - /* Start computing the value. First determine the number of days - * represented by the date, then multiply by the number of seconds/day. - */ - for (Julian = Day - 1, i = 0; i < Month; i++) - Julian += DaysInMonth[i]; - if (Year >= EPOCH) { - for (i = EPOCH; i < Year; i++) - Julian += 365 + IsLeapYear(i); - } else { - for (i = (int)Year; i < EPOCH; i++) - Julian -= 365 + IsLeapYear(i); - } - Julian *= SECSPERDAY; - - /* Add the timezone offset ?? */ - Julian += TclDateTimezone * 60L; - - /* Add the number of seconds represented by the time component */ - if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0) - return -1; - Julian += tod; - - /* Perform a preliminary DST compensation ?? */ - if (DSTmode == DSTon - || (DSTmode == DSTmaybe && TclpGetDate((time_t *)&Julian, 0)->tm_isdst)) - Julian -= 60 * 60; - *TimePtr = Julian; - return 0; -} - - -static time_t -DSTcorrect(Start, Future) - time_t Start; - time_t Future; -{ - time_t StartDay; - time_t FutureDay; - StartDay = (TclpGetDate((time_t *)&Start, 0)->tm_hour + 1) % 24; - FutureDay = (TclpGetDate((time_t *)&Future, 0)->tm_hour + 1) % 24; - return (Future - Start) + (StartDay - FutureDay) * 60L * 60L; -} - - -static time_t -NamedDay(Start, DayOrdinal, DayNumber) - time_t Start; - time_t DayOrdinal; - time_t DayNumber; -{ - struct tm *tm; - time_t now; - - now = Start; - tm = TclpGetDate((time_t *)&now, 0); - now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7); - now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); - return DSTcorrect(Start, now); -} - -static time_t -NamedMonth(Start, MonthOrdinal, MonthNumber) - time_t Start; - time_t MonthOrdinal; - time_t MonthNumber; -{ - struct tm *tm; - time_t now; - int result; - - now = Start; - tm = TclpGetDate((time_t *)&now, 0); - /* To compute the next n'th month, we use this alg: - * add n to year value - * if currentMonth < requestedMonth decrement year value by 1 (so that - * doing next february from january gives us february of the current year) - * set day to 1, time to 0 - */ - tm->tm_year += (int)MonthOrdinal; - if (tm->tm_mon < MonthNumber - 1) { - tm->tm_year--; - } - result = Convert(MonthNumber, (time_t) 1, tm->tm_year + TM_YEAR_BASE, - (time_t) 0, (time_t) 0, (time_t) 0, MER24, DSTmaybe, &now); - if (result < 0) { - return 0; - } - return DSTcorrect(Start, now); -} - -static int -RelativeMonth(Start, RelMonth, TimePtr) - time_t Start; - time_t RelMonth; - time_t *TimePtr; -{ - struct tm *tm; - time_t Month; - time_t Year; - time_t Julian; - int result; - - if (RelMonth == 0) { - *TimePtr = 0; - return 0; - } - tm = TclpGetDate((time_t *)&Start, 0); - Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth; - Year = Month / 12; - Month = Month % 12 + 1; - result = Convert(Month, (time_t) tm->tm_mday, Year, - (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec, - MER24, DSTmaybe, &Julian); - - /* - * The Julian time returned above is behind by one day, if "month" - * or "year" is used to specify relative time and the GMT flag is true. - * This problem occurs only when the current time is closer to - * midnight, the difference being not more than its time difference - * with GMT. For example, in US/Pacific time zone, the problem occurs - * whenever the current time is between midnight to 8:00am or 7:00amDST. - * See Bug# 413397 for more details and sample script. - * To resolve this bug, we simply add the number of seconds corresponding - * to timezone difference with GMT to Julian time, if GMT flag is true. - */ - - if (TclDateTimezone == 0) { - Julian += TclpGetTimeZone((unsigned long) Start) * 60L; - } - - /* - * The following iteration takes into account the case were we jump - * into a "short month". Far example, "one month from Jan 31" will - * fail because there is no Feb 31. The code below will reduce the - * day and try converting the date until we succed or the date equals - * 28 (which always works unless the date is bad in another way). - */ - - while ((result != 0) && (tm->tm_mday > 28)) { - tm->tm_mday--; - result = Convert(Month, (time_t) tm->tm_mday, Year, - (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec, - MER24, DSTmaybe, &Julian); - } - if (result != 0) { - return -1; - } - *TimePtr = DSTcorrect(Start, Julian); - return 0; -} - - -/* - *----------------------------------------------------------------------------- - * - * RelativeDay -- - * - * Given a starting time and a number of days before or after, compute the - * DST corrected difference between those dates. - * - * Results: - * 1 or -1 indicating success or failure. - * - * Side effects: - * Fills TimePtr with the computed value. - * - *----------------------------------------------------------------------------- - */ - -static int -RelativeDay(Start, RelDay, TimePtr) - time_t Start; - time_t RelDay; - time_t *TimePtr; -{ - time_t new; - - new = Start + (RelDay * 60 * 60 * 24); - *TimePtr = DSTcorrect(Start, new); - return 1; -} - -static int -LookupWord(buff) - char *buff; -{ - register char *p; - register char *q; - register TABLE *tp; - int i; - int abbrev; - - /* - * Make it lowercase. - */ - - Tcl_UtfToLower(buff); - - if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) { - TclDatelval.Meridian = MERam; - return tMERIDIAN; - } - if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) { - TclDatelval.Meridian = MERpm; - return tMERIDIAN; - } - - /* - * See if we have an abbreviation for a month. - */ - if (strlen(buff) == 3) { - abbrev = 1; - } else if (strlen(buff) == 4 && buff[3] == '.') { - abbrev = 1; - buff[3] = '\0'; - } else { - abbrev = 0; - } - - for (tp = MonthDayTable; tp->name; tp++) { - if (abbrev) { - if (strncmp(buff, tp->name, 3) == 0) { - TclDatelval.Number = tp->value; - return tp->type; - } - } else if (strcmp(buff, tp->name) == 0) { - TclDatelval.Number = tp->value; - return tp->type; - } - } - - for (tp = TimezoneTable; tp->name; tp++) { - if (strcmp(buff, tp->name) == 0) { - TclDatelval.Number = tp->value; - return tp->type; - } - } - - for (tp = UnitsTable; tp->name; tp++) { - if (strcmp(buff, tp->name) == 0) { - TclDatelval.Number = tp->value; - return tp->type; - } - } - - /* - * Strip off any plural and try the units table again. - */ - i = strlen(buff) - 1; - if (buff[i] == 's') { - buff[i] = '\0'; - for (tp = UnitsTable; tp->name; tp++) { - if (strcmp(buff, tp->name) == 0) { - TclDatelval.Number = tp->value; - return tp->type; - } - } - } - - for (tp = OtherTable; tp->name; tp++) { - if (strcmp(buff, tp->name) == 0) { - TclDatelval.Number = tp->value; - return tp->type; - } - } - - /* - * Military timezones. - */ - if (buff[1] == '\0' && !(*buff & 0x80) - && isalpha(UCHAR(*buff))) { /* INTL: ISO only */ - for (tp = MilitaryTable; tp->name; tp++) { - if (strcmp(buff, tp->name) == 0) { - TclDatelval.Number = tp->value; - return tp->type; - } - } - } - - /* - * Drop out any periods and try the timezone table again. - */ - for (i = 0, p = q = buff; *q; q++) - if (*q != '.') { - *p++ = *q; - } else { - i++; - } - *p = '\0'; - if (i) { - for (tp = TimezoneTable; tp->name; tp++) { - if (strcmp(buff, tp->name) == 0) { - TclDatelval.Number = tp->value; - return tp->type; - } - } - } - - return tID; -} - - -static int -TclDatelex() -{ - register char c; - register char *p; - char buff[20]; - int Count; - - for ( ; ; ) { - while (isspace(UCHAR(*TclDateInput))) { - TclDateInput++; - } - - if (isdigit(UCHAR(c = *TclDateInput))) { /* INTL: digit */ - /* convert the string into a number; count the number of digits */ - Count = 0; - for (TclDatelval.Number = 0; - isdigit(UCHAR(c = *TclDateInput++)); ) { /* INTL: digit */ - TclDatelval.Number = 10 * TclDatelval.Number + c - '0'; - Count++; - } - TclDateInput--; - /* A number with 6 or more digits is considered an ISO 8601 base */ - if (Count >= 6) { - return tISOBASE; - } else { - return tUNUMBER; - } - } - if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */ - for (p = buff; isalpha(UCHAR(c = *TclDateInput++)) /* INTL: ISO only. */ - || c == '.'; ) { - if (p < &buff[sizeof buff - 1]) { - *p++ = c; - } - } - *p = '\0'; - TclDateInput--; - return LookupWord(buff); - } - if (c != '(') { - return *TclDateInput++; - } - Count = 0; - do { - c = *TclDateInput++; - if (c == '\0') { - return c; - } else if (c == '(') { - Count++; - } else if (c == ')') { - Count--; - } - } while (Count > 0); - } -} - -/* - * Specify zone is of -50000 to force GMT. (This allows BST to work). - */ - -int -TclGetDate(p, now, zone, timePtr) - char *p; - Tcl_WideInt now; - long zone; - Tcl_WideInt *timePtr; -{ - struct tm *tm; - time_t Start; - time_t Time; - time_t tod; - int thisyear; - - TclDateInput = p; - /* now has to be cast to a time_t for 64bit compliance */ - Start = (time_t) now; - tm = TclpGetDate((time_t *) &Start, (zone == -50000)); - thisyear = tm->tm_year + TM_YEAR_BASE; - TclDateYear = thisyear; - TclDateMonth = tm->tm_mon + 1; - TclDateDay = tm->tm_mday; - TclDateTimezone = zone; - if (zone == -50000) { - TclDateDSTmode = DSToff; /* assume GMT */ - TclDateTimezone = 0; - } else { - TclDateDSTmode = DSTmaybe; - } - TclDateHour = 0; - TclDateMinutes = 0; - TclDateSeconds = 0; - TclDateMeridian = MER24; - TclDateRelSeconds = 0; - TclDateRelMonth = 0; - TclDateRelDay = 0; - TclDateRelPointer = NULL; - - TclDateHaveDate = 0; - TclDateHaveDay = 0; - TclDateHaveOrdinalMonth = 0; - TclDateHaveRel = 0; - TclDateHaveTime = 0; - TclDateHaveZone = 0; - - if (TclDateparse() || TclDateHaveTime > 1 || TclDateHaveZone > 1 || TclDateHaveDate > 1 || - TclDateHaveDay > 1 || TclDateHaveOrdinalMonth > 1) { - return -1; - } - - if (TclDateHaveDate || TclDateHaveTime || TclDateHaveDay) { - if (TclDateYear < 0) { - TclDateYear = -TclDateYear; - } - /* - * The following line handles years that are specified using - * only two digits. The line of code below implements a policy - * defined by the X/Open workgroup on the millinium rollover. - * Note: some of those dates may not actually be valid on some - * platforms. The POSIX standard startes that the dates 70-99 - * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038. - * This later definition should work on all platforms. - */ - - if (TclDateYear < 100) { - if (TclDateYear >= 69) { - TclDateYear += 1900; - } else { - TclDateYear += 2000; - } - } - if (Convert(TclDateMonth, TclDateDay, TclDateYear, TclDateHour, TclDateMinutes, TclDateSeconds, - TclDateMeridian, TclDateDSTmode, &Start) < 0) { - return -1; - } - } else { - Start = (time_t) now; - if (!TclDateHaveRel) { - Start -= ((tm->tm_hour * 60L * 60L) + - tm->tm_min * 60L) + tm->tm_sec; - } - } - - Start += TclDateRelSeconds; - if (RelativeMonth(Start, TclDateRelMonth, &Time) < 0) { - return -1; - } - Start += Time; - - if (RelativeDay(Start, TclDateRelDay, &Time) < 0) { - return -1; - } - Start += Time; - - if (TclDateHaveDay && !TclDateHaveDate) { - tod = NamedDay(Start, TclDateDayOrdinal, TclDateDayNumber); - Start += tod; - } - - if (TclDateHaveOrdinalMonth) { - tod = NamedMonth(Start, TclDateMonthOrdinal, TclDateMonth); - Start += tod; - } - - *timePtr = Start; - return 0; -} -static CONST TclDatetabelem TclDateexca[] ={ --1, 1, - 0, -1, - -2, 0, - }; -# define YYNPROD 56 -# define YYLAST 261 -static CONST TclDatetabelem TclDateact[]={ - - 24, 40, 23, 36, 54, 81, 41, 28, 53, 26, - 37, 42, 58, 38, 56, 28, 27, 26, 28, 33, - 26, 32, 61, 50, 27, 80, 76, 27, 51, 75, - 74, 73, 30, 72, 71, 70, 69, 52, 49, 48, - 47, 45, 39, 62, 78, 46, 79, 68, 25, 65, - 60, 67, 66, 55, 44, 21, 63, 11, 10, 9, - 8, 35, 7, 6, 5, 4, 3, 43, 2, 1, - 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 57, 0, 0, 59, 77, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 19, 14, 0, 0, 0, - 16, 28, 22, 26, 0, 12, 13, 17, 0, 15, - 27, 18, 31, 0, 0, 29, 0, 34, 28, 0, - 26, 0, 0, 0, 0, 0, 0, 27, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, - 64 }; -static CONST TclDatetabelem TclDatepact[]={ - --10000000, -43,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000, --10000000,-10000000, -26, -268,-10000000, -259, -226,-10000000, -257, 10, - -227, -212, -228,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000, - -229,-10000000, -230, -240, -231,-10000000,-10000000, -264,-10000000, 9, --10000000,-10000000, -249,-10000000,-10000000, -246,-10000000, 4, -2, 2, - 7, 6,-10000000,-10000000, -11, -232,-10000000,-10000000,-10000000,-10000000, - -233,-10000000, -234, -235,-10000000, -237, -238, -239, -242,-10000000, --10000000,-10000000, -1,-10000000,-10000000,-10000000, -12,-10000000, -243, -263, --10000000,-10000000 }; -static CONST TclDatetabelem TclDatepgo[]={ - - 0, 48, 70, 22, 69, 68, 66, 65, 64, 63, - 62, 60, 59, 58, 57, 55 }; -static CONST TclDatetabelem TclDater1[]={ - - 0, 4, 4, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, - 10, 10, 10, 10, 10, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 12, 12, 12, - 13, 11, 11, 15, 15, 15, 15, 15, 2, 2, - 1, 1, 1, 14, 3, 3 }; -static CONST TclDatetabelem TclDater2[]={ - - 0, 0, 4, 3, 3, 3, 3, 3, 3, 3, - 3, 2, 5, 9, 11, 13, 15, 5, 3, 3, - 3, 5, 5, 7, 5, 7, 11, 3, 11, 11, - 5, 9, 5, 3, 7, 5, 7, 7, 15, 5, - 9, 5, 2, 7, 5, 5, 7, 3, 3, 3, - 3, 3, 3, 3, 1, 3 }; -static CONST TclDatetabelem TclDatechk[]={ - --10000000, -4, -5, -6, -7, -8, -9, -10, -11, -12, - -13, -14, 268, 269, 259, 272, 263, 270, 274, 258, - -2, -15, 265, 45, 43, -1, 266, 273, 264, 261, - 58, 258, 47, 45, 263, -1, 271, 269, 272, 268, - 258, 263, 268, -1, 44, 268, 257, 268, 268, 268, - 263, 268, 268, 272, 268, 44, 263, -1, 258, -1, - 46, -3, 45, 58, 261, 47, 45, 45, 58, 268, - 268, 268, 268, 268, 268, 268, 268, -3, 45, 58, - 268, 268 }; -static CONST TclDatetabelem TclDatedef[]={ - - 1, -2, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 53, 18, 19, 27, 0, 33, 0, 20, - 0, 42, 0, 48, 49, 47, 50, 51, 52, 12, - 0, 22, 0, 0, 32, 44, 17, 0, 39, 30, - 24, 35, 0, 45, 21, 0, 41, 0, 54, 25, - 0, 0, 34, 37, 0, 0, 36, 46, 23, 43, - 0, 13, 0, 0, 55, 0, 0, 0, 0, 31, - 40, 14, 54, 26, 28, 29, 0, 15, 0, 0, - 16, 38 }; -typedef struct -#ifdef __cplusplus - TclDatetoktype -#endif -{ char *t_name; int t_val; } TclDatetoktype; -#ifndef YYDEBUG -# define YYDEBUG 0 /* don't allow debugging */ -#endif - -#if YYDEBUG - -TclDatetoktype TclDatetoks[] = -{ - "tAGO", 257, - "tDAY", 258, - "tDAYZONE", 259, - "tID", 260, - "tMERIDIAN", 261, - "tMINUTE_UNIT", 262, - "tMONTH", 263, - "tMONTH_UNIT", 264, - "tSTARDATE", 265, - "tSEC_UNIT", 266, - "tSNUMBER", 267, - "tUNUMBER", 268, - "tZONE", 269, - "tEPOCH", 270, - "tDST", 271, - "tISOBASE", 272, - "tDAY_UNIT", 273, - "tNEXT", 274, - "-unknown-", -1 /* ends search */ -}; - -char * TclDatereds[] = -{ - "-no such reduction-", - "spec : /* empty */", - "spec : spec item", - "item : time", - "item : zone", - "item : date", - "item : ordMonth", - "item : day", - "item : relspec", - "item : iso", - "item : trek", - "item : number", - "time : tUNUMBER tMERIDIAN", - "time : tUNUMBER ':' tUNUMBER o_merid", - "time : tUNUMBER ':' tUNUMBER '-' tUNUMBER", - "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid", - "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER", - "zone : tZONE tDST", - "zone : tZONE", - "zone : tDAYZONE", - "day : tDAY", - "day : tDAY ','", - "day : tUNUMBER tDAY", - "day : sign tUNUMBER tDAY", - "day : tNEXT tDAY", - "date : tUNUMBER '/' tUNUMBER", - "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER", - "date : tISOBASE", - "date : tUNUMBER '-' tMONTH '-' tUNUMBER", - "date : tUNUMBER '-' tUNUMBER '-' tUNUMBER", - "date : tMONTH tUNUMBER", - "date : tMONTH tUNUMBER ',' tUNUMBER", - "date : tUNUMBER tMONTH", - "date : tEPOCH", - "date : tUNUMBER tMONTH tUNUMBER", - "ordMonth : tNEXT tMONTH", - "ordMonth : tNEXT tUNUMBER tMONTH", - "iso : tISOBASE tZONE tISOBASE", - "iso : tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER", - "iso : tISOBASE tISOBASE", - "trek : tSTARDATE tUNUMBER '.' tUNUMBER", - "relspec : relunits tAGO", - "relspec : relunits", - "relunits : sign tUNUMBER unit", - "relunits : tUNUMBER unit", - "relunits : tNEXT unit", - "relunits : tNEXT tUNUMBER unit", - "relunits : unit", - "sign : '-'", - "sign : '+'", - "unit : tSEC_UNIT", - "unit : tDAY_UNIT", - "unit : tMONTH_UNIT", - "number : tUNUMBER", - "o_merid : /* empty */", - "o_merid : tMERIDIAN", -}; -#endif /* YYDEBUG */ -/* - * Copyright (c) 1993 by Sun Microsystems, Inc. - */ - - -/* -** Skeleton parser driver for yacc output -*/ - -/* -** yacc user known macros and defines -*/ -#define YYERROR goto TclDateerrlab -#define YYACCEPT return(0) -#define YYABORT return(1) -#define YYBACKUP( newtoken, newvalue )\ -{\ - if ( TclDatechar >= 0 || ( TclDater2[ TclDatetmp ] >> 1 ) != 1 )\ - {\ - TclDateerror( "syntax error - cannot backup" );\ - goto TclDateerrlab;\ - }\ - TclDatechar = newtoken;\ - TclDatestate = *TclDateps;\ - TclDatelval = newvalue;\ - goto TclDatenewstate;\ -} -#define YYRECOVERING() (!!TclDateerrflag) -#define YYNEW(type) malloc(sizeof(type) * TclDatenewmax) -#define YYCOPY(to, from, type) \ - (type *) memcpy(to, (char *) from, TclDatemaxdepth * sizeof (type)) -#define YYENLARGE( from, type) \ - (type *) realloc((char *) from, TclDatenewmax * sizeof(type)) -#ifndef YYDEBUG -# define YYDEBUG 1 /* make debugging available */ -#endif - -/* -** user known globals -*/ -int TclDatedebug; /* set to 1 to get debugging */ - -/* -** driver internal defines -*/ -#define YYFLAG (-10000000) - -/* -** global variables used by the parser -*/ -YYSTYPE *TclDatepv; /* top of value stack */ -int *TclDateps; /* top of state stack */ - -int TclDatestate; /* current state */ -int TclDatetmp; /* extra var (lasts between blocks) */ - -int TclDatenerrs; /* number of errors */ -int TclDateerrflag; /* error recovery flag */ -int TclDatechar; /* current input token number */ - - - -#ifdef YYNMBCHARS -#define YYLEX() TclDatecvtok(TclDatelex()) -/* -** TclDatecvtok - return a token if i is a wchar_t value that exceeds 255. -** If i<255, i itself is the token. If i>255 but the neither -** of the 30th or 31st bit is on, i is already a token. -*/ -#if defined(__STDC__) || defined(__cplusplus) -int TclDatecvtok(int i) -#else -int TclDatecvtok(i) int i; -#endif -{ - int first = 0; - int last = YYNMBCHARS - 1; - int mid; - wchar_t j; - - if(i&0x60000000){/*Must convert to a token. */ - if( TclDatembchars[last].character < i ){ - return i;/*Giving up*/ - } - while ((last>=first)&&(first>=0)) {/*Binary search loop*/ - mid = (first+last)/2; - j = TclDatembchars[mid].character; - if( j==i ){/*Found*/ - return TclDatembchars[mid].tvalue; - }else if( j= 0; - TclDate_i++ ) - { - if ( TclDatetoks[TclDate_i].t_val == TclDatechar ) - break; - } - printf( "%s\n", TclDatetoks[TclDate_i].t_name ); - } - } -#endif /* YYDEBUG */ - if ( ++TclDate_ps >= &TclDates[ TclDatemaxdepth ] ) /* room on stack? */ - { - /* - ** reallocate and recover. Note that pointers - ** have to be reset, or bad things will happen - */ - long TclDateps_index = (TclDate_ps - TclDates); - long TclDatepv_index = (TclDate_pv - TclDatev); - long TclDatepvt_index = (TclDatepvt - TclDatev); - int TclDatenewmax; -#ifdef YYEXPAND - TclDatenewmax = YYEXPAND(TclDatemaxdepth); -#else - TclDatenewmax = 2 * TclDatemaxdepth; /* double table size */ - if (TclDatemaxdepth == YYMAXDEPTH) /* first time growth */ - { - char *newTclDates = (char *)YYNEW(int); - char *newTclDatev = (char *)YYNEW(YYSTYPE); - if (newTclDates != 0 && newTclDatev != 0) - { - TclDates = YYCOPY(newTclDates, TclDates, int); - TclDatev = YYCOPY(newTclDatev, TclDatev, YYSTYPE); - } - else - TclDatenewmax = 0; /* failed */ - } - else /* not first time */ - { - TclDates = YYENLARGE(TclDates, int); - TclDatev = YYENLARGE(TclDatev, YYSTYPE); - if (TclDates == 0 || TclDatev == 0) - TclDatenewmax = 0; /* failed */ - } -#endif - if (TclDatenewmax <= TclDatemaxdepth) /* tables not expanded */ - { - TclDateerror( "yacc stack overflow" ); - YYABORT; - } - TclDatemaxdepth = TclDatenewmax; - - TclDate_ps = TclDates + TclDateps_index; - TclDate_pv = TclDatev + TclDatepv_index; - TclDatepvt = TclDatev + TclDatepvt_index; - } - *TclDate_ps = TclDate_state; - *++TclDate_pv = TclDateval; - - /* - ** we have a new state - find out what to do - */ - TclDate_newstate: - if ( ( TclDate_n = TclDatepact[ TclDate_state ] ) <= YYFLAG ) - goto TclDatedefault; /* simple state */ -#if YYDEBUG - /* - ** if debugging, need to mark whether new token grabbed - */ - TclDatetmp = TclDatechar < 0; -#endif - if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) ) - TclDatechar = 0; /* reached EOF */ -#if YYDEBUG - if ( TclDatedebug && TclDatetmp ) - { - register int TclDate_i; - - printf( "Received token " ); - if ( TclDatechar == 0 ) - printf( "end-of-file\n" ); - else if ( TclDatechar < 0 ) - printf( "-none-\n" ); - else - { - for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0; - TclDate_i++ ) - { - if ( TclDatetoks[TclDate_i].t_val == TclDatechar ) - break; - } - printf( "%s\n", TclDatetoks[TclDate_i].t_name ); - } - } -#endif /* YYDEBUG */ - if ( ( ( TclDate_n += TclDatechar ) < 0 ) || ( TclDate_n >= YYLAST ) ) - goto TclDatedefault; - if ( TclDatechk[ TclDate_n = TclDateact[ TclDate_n ] ] == TclDatechar ) /*valid shift*/ - { - TclDatechar = -1; - TclDateval = TclDatelval; - TclDate_state = TclDate_n; - if ( TclDateerrflag > 0 ) - TclDateerrflag--; - goto TclDate_stack; - } - - TclDatedefault: - if ( ( TclDate_n = TclDatedef[ TclDate_state ] ) == -2 ) - { -#if YYDEBUG - TclDatetmp = TclDatechar < 0; -#endif - if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) ) - TclDatechar = 0; /* reached EOF */ -#if YYDEBUG - if ( TclDatedebug && TclDatetmp ) - { - register int TclDate_i; - - printf( "Received token " ); - if ( TclDatechar == 0 ) - printf( "end-of-file\n" ); - else if ( TclDatechar < 0 ) - printf( "-none-\n" ); - else - { - for ( TclDate_i = 0; - TclDatetoks[TclDate_i].t_val >= 0; - TclDate_i++ ) - { - if ( TclDatetoks[TclDate_i].t_val - == TclDatechar ) - { - break; - } - } - printf( "%s\n", TclDatetoks[TclDate_i].t_name ); - } - } -#endif /* YYDEBUG */ - /* - ** look through exception table - */ - { - register CONST int *TclDatexi = TclDateexca; - - while ( ( *TclDatexi != -1 ) || - ( TclDatexi[1] != TclDate_state ) ) - { - TclDatexi += 2; - } - while ( ( *(TclDatexi += 2) >= 0 ) && - ( *TclDatexi != TclDatechar ) ) - ; - if ( ( TclDate_n = TclDatexi[1] ) < 0 ) - YYACCEPT; - } - } - - /* - ** check for syntax error - */ - if ( TclDate_n == 0 ) /* have an error */ - { - /* no worry about speed here! */ - switch ( TclDateerrflag ) - { - case 0: /* new error */ - TclDateerror( "syntax error" ); - goto skip_init; - /* - ** get globals into registers. - ** we have a user generated syntax type error - */ - TclDate_pv = TclDatepv; - TclDate_ps = TclDateps; - TclDate_state = TclDatestate; - skip_init: - TclDatenerrs++; - /* FALLTHRU */ - case 1: - case 2: /* incompletely recovered error */ - /* try again... */ - TclDateerrflag = 3; - /* - ** find state where "error" is a legal - ** shift action - */ - while ( TclDate_ps >= TclDates ) - { - TclDate_n = TclDatepact[ *TclDate_ps ] + YYERRCODE; - if ( TclDate_n >= 0 && TclDate_n < YYLAST && - TclDatechk[TclDateact[TclDate_n]] == YYERRCODE) { - /* - ** simulate shift of "error" - */ - TclDate_state = TclDateact[ TclDate_n ]; - goto TclDate_stack; - } - /* - ** current state has no shift on - ** "error", pop stack - */ -#if YYDEBUG -# define _POP_ "Error recovery pops state %d, uncovers state %d\n" - if ( TclDatedebug ) - printf( _POP_, *TclDate_ps, - TclDate_ps[-1] ); -# undef _POP_ -#endif - TclDate_ps--; - TclDate_pv--; - } - /* - ** there is no state on stack with "error" as - ** a valid shift. give up. - */ - YYABORT; - case 3: /* no shift yet; eat a token */ -#if YYDEBUG - /* - ** if debugging, look up token in list of - ** pairs. 0 and negative shouldn't occur, - ** but since timing doesn't matter when - ** debugging, it doesn't hurt to leave the - ** tests here. - */ - if ( TclDatedebug ) - { - register int TclDate_i; - - printf( "Error recovery discards " ); - if ( TclDatechar == 0 ) - printf( "token end-of-file\n" ); - else if ( TclDatechar < 0 ) - printf( "token -none-\n" ); - else - { - for ( TclDate_i = 0; - TclDatetoks[TclDate_i].t_val >= 0; - TclDate_i++ ) - { - if ( TclDatetoks[TclDate_i].t_val - == TclDatechar ) - { - break; - } - } - printf( "token %s\n", - TclDatetoks[TclDate_i].t_name ); - } - } -#endif /* YYDEBUG */ - if ( TclDatechar == 0 ) /* reached EOF. quit */ - YYABORT; - TclDatechar = -1; - goto TclDate_newstate; - } - }/* end if ( TclDate_n == 0 ) */ - /* - ** reduction by production TclDate_n - ** put stack tops, etc. so things right after switch - */ -#if YYDEBUG - /* - ** if debugging, print the string that is the user's - ** specification of the reduction which is just about - ** to be done. - */ - if ( TclDatedebug ) - printf( "Reduce by (%d) \"%s\"\n", - TclDate_n, TclDatereds[ TclDate_n ] ); -#endif - TclDatetmp = TclDate_n; /* value to switch over */ - TclDatepvt = TclDate_pv; /* $vars top of value stack */ - /* - ** Look in goto table for next state - ** Sorry about using TclDate_state here as temporary - ** register variable, but why not, if it works... - ** If TclDater2[ TclDate_n ] doesn't have the low order bit - ** set, then there is no action to be done for - ** this reduction. So, no saving & unsaving of - ** registers done. The only difference between the - ** code just after the if and the body of the if is - ** the goto TclDate_stack in the body. This way the test - ** can be made before the choice of what to do is needed. - */ - { - /* length of production doubled with extra bit */ - register int TclDate_len = TclDater2[ TclDate_n ]; - - if ( !( TclDate_len & 01 ) ) - { - TclDate_len >>= 1; - TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */ - TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] + - *( TclDate_ps -= TclDate_len ) + 1; - if ( TclDate_state >= YYLAST || - TclDatechk[ TclDate_state = - TclDateact[ TclDate_state ] ] != -TclDate_n ) - { - TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ]; - } - goto TclDate_stack; - } - TclDate_len >>= 1; - TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */ - TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] + - *( TclDate_ps -= TclDate_len ) + 1; - if ( TclDate_state >= YYLAST || - TclDatechk[ TclDate_state = TclDateact[ TclDate_state ] ] != -TclDate_n ) - { - TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ]; - } - } - /* save until reenter driver code */ - TclDatestate = TclDate_state; - TclDateps = TclDate_ps; - TclDatepv = TclDate_pv; - } - /* - ** code supplied by user is placed in this switch - */ - switch( TclDatetmp ) - { - -case 3:{ - TclDateHaveTime++; - } break; -case 4:{ - TclDateHaveZone++; - } break; -case 5:{ - TclDateHaveDate++; - } break; -case 6:{ - TclDateHaveOrdinalMonth++; - } break; -case 7:{ - TclDateHaveDay++; - } break; -case 8:{ - TclDateHaveRel++; - } break; -case 9:{ - TclDateHaveTime++; - TclDateHaveDate++; - } break; -case 10:{ - TclDateHaveTime++; - TclDateHaveDate++; - TclDateHaveRel++; - } break; -case 12:{ - TclDateHour = TclDatepvt[-1].Number; - TclDateMinutes = 0; - TclDateSeconds = 0; - TclDateMeridian = TclDatepvt[-0].Meridian; - } break; -case 13:{ - TclDateHour = TclDatepvt[-3].Number; - TclDateMinutes = TclDatepvt[-1].Number; - TclDateSeconds = 0; - TclDateMeridian = TclDatepvt[-0].Meridian; - } break; -case 14:{ - TclDateHour = TclDatepvt[-4].Number; - TclDateMinutes = TclDatepvt[-2].Number; - TclDateMeridian = MER24; - TclDateDSTmode = DSToff; - TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60); - } break; -case 15:{ - TclDateHour = TclDatepvt[-5].Number; - TclDateMinutes = TclDatepvt[-3].Number; - TclDateSeconds = TclDatepvt[-1].Number; - TclDateMeridian = TclDatepvt[-0].Meridian; - } break; -case 16:{ - TclDateHour = TclDatepvt[-6].Number; - TclDateMinutes = TclDatepvt[-4].Number; - TclDateSeconds = TclDatepvt[-2].Number; - TclDateMeridian = MER24; - TclDateDSTmode = DSToff; - TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60); - } break; -case 17:{ - TclDateTimezone = TclDatepvt[-1].Number; - TclDateDSTmode = DSTon; - } break; -case 18:{ - TclDateTimezone = TclDatepvt[-0].Number; - TclDateDSTmode = DSToff; - } break; -case 19:{ - TclDateTimezone = TclDatepvt[-0].Number; - TclDateDSTmode = DSTon; - } break; -case 20:{ - TclDateDayOrdinal = 1; - TclDateDayNumber = TclDatepvt[-0].Number; - } break; -case 21:{ - TclDateDayOrdinal = 1; - TclDateDayNumber = TclDatepvt[-1].Number; - } break; -case 22:{ - TclDateDayOrdinal = TclDatepvt[-1].Number; - TclDateDayNumber = TclDatepvt[-0].Number; - } break; -case 23:{ - TclDateDayOrdinal = TclDatepvt[-2].Number * TclDatepvt[-1].Number; - TclDateDayNumber = TclDatepvt[-0].Number; - } break; -case 24:{ - TclDateDayOrdinal = 2; - TclDateDayNumber = TclDatepvt[-0].Number; - } break; -case 25:{ - TclDateMonth = TclDatepvt[-2].Number; - TclDateDay = TclDatepvt[-0].Number; - } break; -case 26:{ - TclDateMonth = TclDatepvt[-4].Number; - TclDateDay = TclDatepvt[-2].Number; - TclDateYear = TclDatepvt[-0].Number; - } break; -case 27:{ - TclDateYear = TclDatepvt[-0].Number / 10000; - TclDateMonth = (TclDatepvt[-0].Number % 10000)/100; - TclDateDay = TclDatepvt[-0].Number % 100; - } break; -case 28:{ - TclDateDay = TclDatepvt[-4].Number; - TclDateMonth = TclDatepvt[-2].Number; - TclDateYear = TclDatepvt[-0].Number; - } break; -case 29:{ - TclDateMonth = TclDatepvt[-2].Number; - TclDateDay = TclDatepvt[-0].Number; - TclDateYear = TclDatepvt[-4].Number; - } break; -case 30:{ - TclDateMonth = TclDatepvt[-1].Number; - TclDateDay = TclDatepvt[-0].Number; - } break; -case 31:{ - TclDateMonth = TclDatepvt[-3].Number; - TclDateDay = TclDatepvt[-2].Number; - TclDateYear = TclDatepvt[-0].Number; - } break; -case 32:{ - TclDateMonth = TclDatepvt[-0].Number; - TclDateDay = TclDatepvt[-1].Number; - } break; -case 33:{ - TclDateMonth = 1; - TclDateDay = 1; - TclDateYear = EPOCH; - } break; -case 34:{ - TclDateMonth = TclDatepvt[-1].Number; - TclDateDay = TclDatepvt[-2].Number; - TclDateYear = TclDatepvt[-0].Number; - } break; -case 35:{ - TclDateMonthOrdinal = 1; - TclDateMonth = TclDatepvt[-0].Number; - } break; -case 36:{ - TclDateMonthOrdinal = TclDatepvt[-1].Number; - TclDateMonth = TclDatepvt[-0].Number; - } break; -case 37:{ - if (TclDatepvt[-1].Number != HOUR(- 7)) YYABORT; - TclDateYear = TclDatepvt[-2].Number / 10000; - TclDateMonth = (TclDatepvt[-2].Number % 10000)/100; - TclDateDay = TclDatepvt[-2].Number % 100; - TclDateHour = TclDatepvt[-0].Number / 10000; - TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100; - TclDateSeconds = TclDatepvt[-0].Number % 100; - } break; -case 38:{ - if (TclDatepvt[-5].Number != HOUR(- 7)) YYABORT; - TclDateYear = TclDatepvt[-6].Number / 10000; - TclDateMonth = (TclDatepvt[-6].Number % 10000)/100; - TclDateDay = TclDatepvt[-6].Number % 100; - TclDateHour = TclDatepvt[-4].Number; - TclDateMinutes = TclDatepvt[-2].Number; - TclDateSeconds = TclDatepvt[-0].Number; - } break; -case 39:{ - TclDateYear = TclDatepvt[-1].Number / 10000; - TclDateMonth = (TclDatepvt[-1].Number % 10000)/100; - TclDateDay = TclDatepvt[-1].Number % 100; - TclDateHour = TclDatepvt[-0].Number / 10000; - TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100; - TclDateSeconds = TclDatepvt[-0].Number % 100; - } break; -case 40:{ - /* - * Offset computed year by -377 so that the returned years will - * be in a range accessible with a 32 bit clock seconds value - */ - TclDateYear = TclDatepvt[-2].Number/1000 + 2323 - 377; - TclDateDay = 1; - TclDateMonth = 1; - TclDateRelDay += ((TclDatepvt[-2].Number%1000)*(365 + IsLeapYear(TclDateYear)))/1000; - TclDateRelSeconds += TclDatepvt[-0].Number * 144 * 60; - } break; -case 41:{ - TclDateRelSeconds *= -1; - TclDateRelMonth *= -1; - TclDateRelDay *= -1; - } break; -case 43:{ *TclDateRelPointer += TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; -case 44:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; -case 45:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break; -case 46:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; -case 47:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break; -case 48:{ TclDateval.Number = -1; } break; -case 49:{ TclDateval.Number = 1; } break; -case 50:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelSeconds; } break; -case 51:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelDay; } break; -case 52:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelMonth; } break; -case 53:{ - if (TclDateHaveTime && TclDateHaveDate && !TclDateHaveRel) { - TclDateYear = TclDatepvt[-0].Number; - } else { - TclDateHaveTime++; - if (TclDatepvt[-0].Number < 100) { - TclDateHour = TclDatepvt[-0].Number; - TclDateMinutes = 0; - } else { - TclDateHour = TclDatepvt[-0].Number / 100; - TclDateMinutes = TclDatepvt[-0].Number % 100; - } - TclDateSeconds = 0; - TclDateMeridian = MER24; - } - } break; -case 54:{ - TclDateval.Meridian = MER24; - } break; -case 55:{ - TclDateval.Meridian = TclDatepvt[-0].Meridian; - } break; - } - goto TclDatestack; /* reset registers in driver code */ -} - diff --git a/tclUnixTime.c b/tclUnixTime.c deleted file mode 100644 index c285365..0000000 --- a/tclUnixTime.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * tclUnixTime.c -- - * - * Contains Unix specific versions of Tcl functions that - * obtain time values from the operating system. - * - * Copyright (c) 1995 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclUnixTime.c,v 1.1 2012/03/29 08:45:52 koennecke Exp $ - */ - -#include -#include -#include -#include - -#define TM_YEAR_BASE 1900 -#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) - -/* - * TclpGetDate is coded to return a pointer to a 'struct tm'. For - * thread safety, this structure must be in thread-specific data. - * The 'tmKey' variable is the key to this buffer. - */ - -static Tcl_ThreadDataKey tmKey; -typedef struct ThreadSpecificData { - struct tm gmtime_buf; - struct tm localtime_buf; -} ThreadSpecificData; - -/* - * If we fall back on the thread-unsafe versions of gmtime and localtime, - * use this mutex to try to protect them. - */ - -TCL_DECLARE_MUTEX(tmMutex) - -static char* lastTZ = NULL; /* Holds the last setting of the - * TZ environment variable, or an - * empty string if the variable was - * not set. */ - -/* Static functions declared in this file */ - -static void SetTZIfNecessary _ANSI_ARGS_((void)); -static void CleanupMemory _ANSI_ARGS_((ClientData)); - -/* - *----------------------------------------------------------------------------- - * - * TclpGetSeconds -- - * - * This procedure returns the number of seconds from the epoch. On - * most Unix systems the epoch is Midnight Jan 1, 1970 GMT. - * - * Results: - * Number of seconds from the epoch. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -unsigned long -TclpGetSeconds() -{ - return time((time_t *) NULL); -} - -/* - *----------------------------------------------------------------------------- - * - * TclpGetClicks -- - * - * This procedure returns a value that represents the highest resolution - * clock available on the system. There are no garantees on what the - * resolution will be. In Tcl we will call this value a "click". The - * start time is also system dependant. - * - * Results: - * Number of clicks from some start time. - * - * Side effects: - * None. - * - *----------------------------------------------------------------------------- - */ - -unsigned long -TclpGetClicks() -{ - unsigned long now; -#ifdef NO_GETTOD - struct tms dummy; -#else - struct timeval date; -#endif - -#ifdef NO_GETTOD - now = (unsigned long) times(&dummy); -#else - gettimeofday(&date, NULL); - now = date.tv_sec*1000000 + date.tv_usec; -#endif - - return now; -} - -/* - *---------------------------------------------------------------------- - * - * TclpGetTimeZone -- - * - * Determines the current timezone. The method varies wildly - * between different platform implementations, so its hidden in - * this function. - * - * Results: - * The return value is the local time zone, measured in - * minutes away from GMT (-ve for east, +ve for west). - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -TclpGetTimeZone (currentTime) - unsigned long currentTime; -{ - /* - * We prefer first to use the time zone in "struct tm" if the - * structure contains such a member. Following that, we try - * to locate the external 'timezone' variable and use its value. - * If both of those methods fail, we attempt to convert a known - * time to local time and use the difference from UTC as the local - * time zone. In all cases, we need to undo any Daylight Saving Time - * adjustment. - */ - -#if defined(HAVE_TM_TZADJ) -# define TCL_GOT_TIMEZONE - - /* Struct tm contains tm_tzadj - that value may be used. */ - - time_t curTime = (time_t) currentTime; - struct tm *timeDataPtr = TclpLocaltime((time_t *) &curTime); - int timeZone; - - timeZone = timeDataPtr->tm_tzadj / 60; - if (timeDataPtr->tm_isdst) { - timeZone += 60; - } - - return timeZone; - -#endif - -#if defined(HAVE_TM_GMTOFF) && !defined (TCL_GOT_TIMEZONE) -# define TCL_GOT_TIMEZONE - - /* Struct tm contains tm_gmtoff - that value may be used. */ - - time_t curTime = (time_t) currentTime; - struct tm *timeDataPtr = TclpLocaltime((time_t *) &curTime); - int timeZone; - - timeZone = -(timeDataPtr->tm_gmtoff / 60); - if (timeDataPtr->tm_isdst) { - timeZone += 60; - } - - return timeZone; - -#endif - -#if defined(HAVE_TIMEZONE_VAR) && !defined(TCL_GOT_TIMEZONE) && !defined(USE_DELTA_FOR_TZ) -# define TCL_GOT_TIMEZONE - - int timeZone; - - /* The 'timezone' external var is present and may be used. */ - - SetTZIfNecessary(); - - /* - * Note: this is not a typo in "timezone" below! See tzset - * documentation for details. - */ - - timeZone = timezone / 60; - return timeZone; - -#endif - -#if !defined(TCL_GOT_TIMEZONE) -#define TCL_GOT_TIMEZONE 1 - /* - * Fallback - determine time zone with a known reference time. - */ - - int timeZone; - time_t tt; - struct tm *stm; - tt = 849268800L; /* 1996-11-29 12:00:00 GMT */ - stm = TclpLocaltime((time_t *) &tt); /* eg 1996-11-29 6:00:00 CST6CDT */ - /* The calculation below assumes a max of +12 or -12 hours from GMT */ - timeZone = (12 - stm->tm_hour)*60 + (0 - stm->tm_min); - if ( stm -> tm_isdst ) { - timeZone += 60; - } - return timeZone; /* eg +360 for CST6CDT */ -#endif - -#ifndef TCL_GOT_TIMEZONE - /* - * Cause compile error, we don't know how to get timezone. - */ - -#error autoconf did not figure out how to determine the timezone. - -#endif - -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_GetTime -- - * - * Gets the current system time in seconds and microseconds - * since the beginning of the epoch: 00:00 UCT, January 1, 1970. - * - * Results: - * Returns the current time in timePtr. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_GetTime(timePtr) - Tcl_Time *timePtr; /* Location to store time information. */ -{ - struct timeval tv; - - (void) gettimeofday(&tv, NULL); - timePtr->sec = tv.tv_sec; - timePtr->usec = tv.tv_usec; -} - -/* - *---------------------------------------------------------------------- - * - * TclpGetDate -- - * - * This function converts between seconds and struct tm. If - * useGMT is true, then the returned date will be in Greenwich - * Mean Time (GMT). Otherwise, it will be in the local time zone. - * - * Results: - * Returns a static tm structure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -struct tm * -TclppGetDate(time, useGMT) - time_t time; - int useGMT; -{ - time_t mtime = time; - if (useGMT) { - return TclpGmtime(&mtime); - } else { - return TclpLocaltime(&mtime); - } -} - -/* - *---------------------------------------------------------------------- - * - * TclpStrftime -- - * - * On Unix, we can safely call the native strftime implementation, - * and also ignore the useGMT parameter. - * - * Results: - * The normal strftime result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -size_t -TclpStrftime(s, maxsize, format, t, useGMT) - char *s; - size_t maxsize; - CONST char *format; - CONST struct tm *t; - int useGMT; -{ - if (format[0] == '%' && format[1] == 'Q') { - /* Format as a stardate */ - sprintf(s, "Stardate %2d%03d.%01d", - (((t->tm_year + TM_YEAR_BASE) + 377) - 2323), - (((t->tm_yday + 1) * 1000) / - (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))), - (((t->tm_hour * 60) + t->tm_min)/144)); - return(strlen(s)); - } - setlocale(LC_TIME, ""); - return strftime(s, maxsize, format, t); -} - -/* - *---------------------------------------------------------------------- - * - * TclpGmtime -- - * - * Wrapper around the 'gmtime' library function to make it thread - * safe. - * - * Results: - * Returns a pointer to a 'struct tm' in thread-specific data. - * - * Side effects: - * Invokes gmtime or gmtime_r as appropriate. - * - *---------------------------------------------------------------------- - */ - -struct tm * -TclpGmtime( tt ) - CONST time_t *tt; -{ - CONST time_t *timePtr = (CONST time_t *) tt; - /* Pointer to the number of seconds - * since the local system's epoch */ - - /* - * Get a thread-local buffer to hold the returned time. - */ - - ThreadSpecificData *tsdPtr = TCL_TSD_INIT( &tmKey ); -#ifdef HAVE_GMTIME_R - gmtime_r(timePtr, &( tsdPtr->gmtime_buf )); -#else - Tcl_MutexLock( &tmMutex ); - memcpy( (VOID *) &( tsdPtr->gmtime_buf ), - (VOID *) gmtime( timePtr ), - sizeof( struct tm ) ); - Tcl_MutexUnlock( &tmMutex ); -#endif - return &( tsdPtr->gmtime_buf ); -} -/* - * Forwarder for obsolete item in Stubs - */ -struct tm* -TclpGmtime_unix( timePtr ) - CONST time_t *timePtr; -{ - return TclpGmtime( timePtr ); -} - -/* - *---------------------------------------------------------------------- - * - * TclpLocaltime -- - * - * Wrapper around the 'localtime' library function to make it thread - * safe. - * - * Results: - * Returns a pointer to a 'struct tm' in thread-specific data. - * - * Side effects: - * Invokes localtime or localtime_r as appropriate. - * - *---------------------------------------------------------------------- - */ - -struct tm * -TclpLocaltime( tt ) - CONST time_t *tt; -{ - CONST time_t *timePtr = (CONST time_t *) tt; - /* Pointer to the number of seconds - * since the local system's epoch */ - /* - * Get a thread-local buffer to hold the returned time. - */ - - ThreadSpecificData *tsdPtr = TCL_TSD_INIT( &tmKey ); - SetTZIfNecessary(); -#ifdef HAVE_LOCALTIME_R - localtime_r( timePtr, &( tsdPtr->localtime_buf ) ); -#else - Tcl_MutexLock( &tmMutex ); - memcpy( (VOID *) &( tsdPtr -> localtime_buf ), - (VOID *) localtime( timePtr ), - sizeof( struct tm ) ); - Tcl_MutexUnlock( &tmMutex ); -#endif - return &( tsdPtr->localtime_buf ); -} -/* - * Forwarder for obsolete item in Stubs - */ -struct tm* -TclpLocaltime_unix( timePtr ) - CONST time_t *timePtr; -{ - return TclpLocaltime( timePtr ); -} - -/* - *---------------------------------------------------------------------- - * - * SetTZIfNecessary -- - * - * Determines whether a call to 'tzset' is needed prior to the - * next call to 'localtime' or examination of the 'timezone' variable. - * - * Results: - * None. - * - * Side effects: - * If 'tzset' has never been called in the current process, or if - * the value of the environment variable TZ has changed since the - * last call to 'tzset', then 'tzset' is called again. - * - *---------------------------------------------------------------------- - */ - -static void -SetTZIfNecessary() { - - CONST char* newTZ = getenv( "TZ" ); - Tcl_MutexLock(&tmMutex); - if ( newTZ == NULL ) { - newTZ = ""; - } - if ( lastTZ == NULL || strcmp( lastTZ, newTZ ) ) { - tzset(); - if ( lastTZ == NULL ) { - Tcl_CreateExitHandler( CleanupMemory, (ClientData) NULL ); - } else { - Tcl_Free( lastTZ ); - } - lastTZ = ckalloc( strlen( newTZ ) + 1 ); - strcpy( lastTZ, newTZ ); - } - Tcl_MutexUnlock(&tmMutex); - -} - -/* - *---------------------------------------------------------------------- - * - * CleanupMemory -- - * - * Releases the private copy of the TZ environment variable - * upon exit from Tcl. - * - * Results: - * None. - * - * Side effects: - * Frees allocated memory. - * - *---------------------------------------------------------------------- - */ - -static void -CleanupMemory( ClientData ignored ) -{ - ckfree( lastTZ ); -} diff --git a/utils/deploysics b/utils/deploysics new file mode 100755 index 0000000..4705fb6 --- /dev/null +++ b/utils/deploysics @@ -0,0 +1,45 @@ +#!/usr/bin/tclsh +#---------------------------------------------------------- +# A script for deploying SICS servers easily +# +# Mark Koennecke, April 2015 +#---------------------------------------------------------- + +set instlist [list amor boa dmc eiger focus hrpt mars \ + morpheus narziss orion poldi rita2 sans sans2 tasp trics] + + +proc execCommand {command} { + puts stdout "Doing $command" + set status [catch {eval exec $command} msg] + if {$status != 0} { + puts stdout "ERROR: $msg " + } +} +#----------------------------------------------------------- +proc replaceServer {inst} { + execCommand "ssh ${inst}@${inst} monit stop sicsserver" + execCommand "ssh ${inst}@${inst} monit stop simserver" + execCommand "scp ./SICServer ${inst}@${inst}:${inst}_sics" + execCommand "ssh ${inst}@${inst} updatesicscommon" + execCommand "ssh ${inst}@${inst} monit start sicsserver" + execCommand "ssh ${inst}@${inst} monit start simserver" +} + +if {[llength $argv] < 1} { + puts stdout "usage:\n\tdeploysics instname| all" + exit 1 +} + +set inst [lindex $argv] + +if {[string compare $inst all] == 0} { + foreach inst $instlist { + replaceServer $inst + } +} else { + replaceServer $inst +} + +puts stdout "Done" + diff --git a/utils/picoscope/Makefile b/utils/picoscope/Makefile new file mode 100644 index 0000000..fd6a500 --- /dev/null +++ b/utils/picoscope/Makefile @@ -0,0 +1,17 @@ +#-------------------------------------------------------------- +# This requires the picoscope software to be installed under +# /opt +# +# Mark Koennecke, May 2015 +#-------------------------------------------------------------- + + +picocontrol: picocontrol.o + gcc -g -o picocontrol picocontrol.o -L/opt/picoscope/lib -lps2000a + +.c.o: + gcc -g -c -I/opt/picoscope/include $*.c + +clean: + - rm picocontrol picocontrol.o + diff --git a/utils/picoscope/Makefile.osx b/utils/picoscope/Makefile.osx new file mode 100755 index 0000000..e6dce18 --- /dev/null +++ b/utils/picoscope/Makefile.osx @@ -0,0 +1,17 @@ +#-------------------------------------------------------------- +# This requires the picoscope software to be installed under +# /opt +# +# Mark Koennecke, May 2015 +#-------------------------------------------------------------- + + +picocontrol: picocontrol.o + gcc -g -o picocontrol picocontrol.o -L/Applications/PicoScope6.app/Contents/Resources/lib -lps2000a + +.c.o: + gcc -g -c -I/Applications/PicoScope6.app/Contents/Resources/include $*.c + +clean: + - rm picocontrol picocontrol.o + diff --git a/utils/picoscope/PS2000Acon.c b/utils/picoscope/PS2000Acon.c new file mode 100644 index 0000000..775f6f3 --- /dev/null +++ b/utils/picoscope/PS2000Acon.c @@ -0,0 +1,2472 @@ +/*********************************************************************************************************************************************** + * + * Filename: PS2000Acon.c + * + * Copyright: Pico Technology Limited 2010 + * + * Author: RPM + * + * Description: + * This is a console mode program that demonstrates how to use the + * PicoScope 2000a series API. + * + * Examples: + * Collect a block of samples immediately + * Collect a block of samples when a trigger event occurs + * Collect a stream of data immediately + * Collect a stream of data when a trigger event occurs + * Set Signal Generator, using standard or custom signals + * + * Digital Examples (MSO variants only): + * Collect a block of digital samples immediately + * Collect a block of digital samples when a trigger event occurs + * Collect a block of analogue & digital samples when analogue AND digital trigger events occurs + * Collect a block of analogue & digital samples when analogue OR digital trigger events occurs + * Collect a stream of digital data immediately + * Collect a stream of digital data and show aggregated values + * + * + * + * To build this application: + * Set up a project for a 32-bit console mode application + * Add this file to the project + * Add PS2000A.lib to the project + * Add ps2000aApi.h and picoStatus.h to the project + * Build the project + * + ******************************************************************************************************************************************************/ +#include + +/* Headers for Windows */ +#ifdef _WIN32 +#include "windows.h" +#include +#include "..\ps2000aApi.h" +#else +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef PICO_STATUS +#include +#endif + +#define Sleep(a) usleep(1000*a) +#define scanf_s scanf +#define fscanf_s fscanf +#define memcpy_s(a,b,c,d) memcpy(a,c,d) + +typedef enum enBOOL +{ + FALSE, TRUE +} BOOL; + +/* A function to detect a keyboard press on Linux */ +int32_t _getch() +{ + struct termios oldt, newt; + int32_t ch; + int32_t bytesWaiting; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + setbuf(stdin, NULL); + do + { + ioctl(STDIN_FILENO, FIONREAD, &bytesWaiting); + if (bytesWaiting) + getchar(); + } while (bytesWaiting); + + ch = getchar(); + + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return ch; +} + +int32_t _kbhit() +{ + struct termios oldt, newt; + int32_t bytesWaiting; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + setbuf(stdin, NULL); + ioctl(STDIN_FILENO, FIONREAD, &bytesWaiting); + + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return bytesWaiting; +} + +int32_t fopen_s(FILE ** a, const char * b, const char * c) +{ + FILE * fp = fopen(b, c); + *a = fp; + return (fp > 0) ? 0 : -1; +} + +/* A function to get a single character on Linux */ +#define max(a,b) ((a) > (b) ? a : b) +#define min(a,b) ((a) < (b) ? a : b) +#endif + +#define PREF4 __stdcall + +int32_t cycles = 0; + +#define BUFFER_SIZE 1024 + +#define QUAD_SCOPE 4 +#define DUAL_SCOPE 2 + +typedef enum +{ + ANALOGUE, DIGITAL, AGGREGATED, MIXED +} MODE; + +typedef struct +{ + int16_t DCcoupled; + int16_t range; + int16_t enabled; +} CHANNEL_SETTINGS; + +typedef enum +{ + MODEL_NONE = 0, + MODEL_PS2205 = 0x2205, + MODEL_PS2205MSO = 0xE205, + MODEL_PS2206 = 0x2206, + MODEL_PS2207 = 0x2207, + MODEL_PS2208 = 0x2208, + MODEL_PS2206A = 0xA206, + MODEL_PS2207A = 0xA207, + MODEL_PS2208A = 0xA208, + +} MODEL_TYPE; + +typedef struct tTriggerDirections +{ + PS2000A_THRESHOLD_DIRECTION channelA; + PS2000A_THRESHOLD_DIRECTION channelB; + PS2000A_THRESHOLD_DIRECTION channelC; + PS2000A_THRESHOLD_DIRECTION channelD; + PS2000A_THRESHOLD_DIRECTION ext; + PS2000A_THRESHOLD_DIRECTION aux; +} TRIGGER_DIRECTIONS; + +typedef struct tPwq +{ + PS2000A_PWQ_CONDITIONS * conditions; + int16_t nConditions; + PS2000A_THRESHOLD_DIRECTION direction; + uint32_t lower; + uint32_t upper; + PS2000A_PULSE_WIDTH_TYPE type; +} PWQ; + +typedef struct +{ + int16_t handle; + MODEL_TYPE model; + char modelString[8]; + char serial[10]; + int16_t complete; + int16_t openStatus; + int16_t openProgress; + PS2000A_RANGE firstRange; + PS2000A_RANGE lastRange; + int16_t channelCount; + int16_t maxValue; + int16_t signalGenerator; + int16_t ETS; + int16_t AWGFileSize; + CHANNEL_SETTINGS channelSettings [PS2000A_MAX_CHANNELS]; + int16_t digitalPorts; +}UNIT; + +// Global Variables +uint32_t timebase = 8; +int16_t oversample = 1; +BOOL scaleVoltages = TRUE; + +uint16_t inputRanges[PS2000A_MAX_RANGES] = +{ 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000 }; + +BOOL g_ready = FALSE; +int64_t g_times[PS2000A_MAX_CHANNELS]; +int16_t g_timeUnit; +int32_t g_sampleCount; +uint32_t g_startIndex; +int16_t g_autoStopped; +int16_t g_trig = 0; +uint32_t g_trigAt = 0; +int16_t g_overflow = 0; +char BlockFile[20] = "block.txt"; +char StreamFile[20] = "stream.txt"; + +/**************************************************************************** + * Callback + * used by PS2000A data streaimng collection calls, on receipt of data. + * used to set global flags etc checked by user routines + ****************************************************************************/ +void PREF4 CallBackStreaming(int16_t handle, int32_t noOfSamples, + uint32_t startIndex, int16_t overflow, uint32_t triggerAt, + int16_t triggered, int16_t autoStop, void *pParameter) +{ + // used for streaming + g_sampleCount = noOfSamples; + g_startIndex = startIndex; + g_autoStopped = autoStop; + + // flag to say done reading data + g_ready = TRUE; + + // flags to show if & where a trigger has occurred + g_trig = triggered; + g_trigAt = triggerAt; +} + +/**************************************************************************** + * Callback + * used by PS2000A data block collection calls, on receipt of data. + * used to set global flags etc checked by user routines + ****************************************************************************/ +void PREF4 CallBackBlock(int16_t handle, PICO_STATUS status, void * pParameter) +{ + if (status != PICO_CANCELLED) + g_ready = TRUE; +} + +/**************************************************************************** + * CloseDevice + ****************************************************************************/ +void CloseDevice(UNIT *unit) +{ + ps2000aCloseUnit(unit->handle); +} + +/**************************************************************************** + * SetDefaults - restore default settings + ****************************************************************************/ +void SetDefaults(UNIT * unit) +{ + PICO_STATUS status; + int32_t i; + + status = ps2000aSetEts(unit->handle, PS2000A_ETS_OFF, 0, 0, NULL); // Turn off ETS + + for (i = 0; i < unit->channelCount; i++) // reset channels to most recent settings + { + status + = ps2000aSetChannel( + unit->handle, + (PS2000A_CHANNEL) PS2000A_CHANNEL_A + i, + unit->channelSettings[PS2000A_CHANNEL_A + i].enabled, + (PS2000A_COUPLING) unit->channelSettings[PS2000A_CHANNEL_A + + i].DCcoupled, + (PS2000A_RANGE) unit->channelSettings[PS2000A_CHANNEL_A + + i].range, 0); + } +} + +/**************************************************************************** + * SetDigitals - enable or disable Digital Channels + ****************************************************************************/ +PICO_STATUS SetDigitals(UNIT *unit, int16_t state) +{ + PICO_STATUS status; + + int16_t logicLevel; + float logicVoltage = 1.5; + int16_t maxLogicVoltage = 5; + + int16_t timebase = 1; + int16_t port; + + // Set logic threshold + logicLevel = (int16_t) ((logicVoltage / maxLogicVoltage) + * PS2000A_MAX_LOGIC_LEVEL); + + // Enable or Disable Digital ports + for (port = PS2000A_DIGITAL_PORT0; port <= PS2000A_DIGITAL_PORT1; port++) + { + status = ps2000aSetDigitalPort(unit->handle, + (PS2000A_DIGITAL_PORT) port, state, logicLevel); + printf( + status + ? "SetDigitals:PS2000ASetDigitalPort(Port 0x%X) ------ 0x%08lx \n" + : "", port, status); + } + return status; +} + +/**************************************************************************** + * DisableAnalogue - Disable Analogue Channels + ****************************************************************************/ +PICO_STATUS DisableAnalogue(UNIT *unit) +{ + PICO_STATUS status; + int16_t ch; + + // Turn off analogue channels + for (ch = 0; ch < unit->channelCount; ch++) + { + if ((status = ps2000aSetChannel(unit->handle, (PS2000A_CHANNEL) ch, 0, + PS2000A_DC, PS2000A_50MV, 0)) != PICO_OK) + printf( + "DisableAnalogue:ps2000aSetChannel(channel %d) ------ 0x%08lx \n", + ch, status); + } + return status; +} + +/**************************************************************************** + * adc_to_mv + * + * Convert an 16-bit ADC count into millivolts + ****************************************************************************/ +int32_t adc_to_mv(int32_t raw, int32_t ch, UNIT * unit) +{ + return (raw * inputRanges[ch]) / unit->maxValue; +} + +/**************************************************************************** + * mv_to_adc + * + * Convert a millivolt value into a 16-bit ADC count + * + * (useful for setting trigger thresholds) + ****************************************************************************/ +int16_t mv_to_adc(int16_t mv, int16_t ch, UNIT * unit) +{ + return (mv * unit->maxValue) / inputRanges[ch]; +} + +/**************************************************************************** + * ClearDataBuffers + * + * stops GetData writing values to memory that has been released + ****************************************************************************/ +PICO_STATUS ClearDataBuffers(UNIT * unit) +{ + int32_t i; + PICO_STATUS status; + + for (i = 0; i < unit->channelCount; i++) + { + if ((status = ps2000aSetDataBuffers(unit->handle, (int16_t) i, NULL, + NULL, 0, 0, PS2000A_RATIO_MODE_NONE)) != PICO_OK) + printf( + "ClearDataBuffers:ps2000aSetDataBuffers(channel %d) ------ 0x%08lx \n", + i, status); + } + + for (i = 0; i < unit->digitalPorts; i++) + { + if ((status = ps2000aSetDataBuffer(unit->handle, (PS2000A_CHANNEL) (i + + PS2000A_DIGITAL_PORT0), NULL, 0, 0, PS2000A_RATIO_MODE_NONE)) + != PICO_OK) + printf( + "ClearDataBuffers:ps2000aSetDataBuffer(port 0x%X) ------ 0x%08lx \n", + i + PS2000A_DIGITAL_PORT0, status); + } + + return status; +} + +/**************************************************************************** + * BlockDataHandler + * - Used by all block data routines + * - acquires data (user sets trigger mode before calling), displays 10 items + * and saves all to data.txt + * Input : + * - unit : the unit to use. + * - text : the text to display before the display of data slice + * - offset : the offset into the data buffer to start the display's slice. + ****************************************************************************/ +void BlockDataHandler(UNIT * unit, char * text, int32_t offset, MODE mode) +{ + int32_t i, j; + int32_t timeInterval; + int32_t sampleCount = BUFFER_SIZE; + FILE * fp = NULL; + int32_t maxSamples; + int16_t * buffers[PS2000A_MAX_CHANNEL_BUFFERS]; + int16_t * digiBuffer[PS2000A_MAX_DIGITAL_PORTS]; + int32_t timeIndisposed; + uint16_t digiValue; + PICO_STATUS status; + + if (mode == ANALOGUE || mode == MIXED) // Analogue or (MSO Only) MIXED + { + for (i = 0; i < unit->channelCount; i++) + { + buffers[i * 2] = (int16_t*) malloc(sampleCount * sizeof(int16_t)); + buffers[i * 2 + 1] = (int16_t*) malloc(sampleCount * sizeof(int16_t)); + status = ps2000aSetDataBuffers(unit->handle, (int16_t) i, buffers[i + * 2], buffers[i * 2 + 1], sampleCount, 0, + PS2000A_RATIO_MODE_NONE); + printf( + status + ? "BlockDataHandler:ps2000aSetDataBuffers(channel %d) ------ 0x%08lx \n" + : "", i, status); + } + } + + if (mode == DIGITAL || mode == MIXED) // (MSO Only) Digital or MIXED + { + for (i = 0; i < unit->digitalPorts; i++) + { + digiBuffer[i] = (int16_t*) malloc(sampleCount * sizeof(int16_t)); + status = ps2000aSetDataBuffer(unit->handle, (PS2000A_CHANNEL) (i + + PS2000A_DIGITAL_PORT0), digiBuffer[i], sampleCount, 0, + PS2000A_RATIO_MODE_NONE); + printf( + status + ? "BlockDataHandler:ps2000aSetDataBuffer(port 0x%X) ------ 0x%08lx \n" + : "", i + PS2000A_DIGITAL_PORT0, status); + } + } + + /* find the maximum number of samples, the time interval (in timeUnits), + * the most suitable time units, and the maximum oversample at the current timebase*/ + while (ps2000aGetTimebase(unit->handle, timebase, sampleCount, + &timeInterval, oversample, &maxSamples, 0)) + { + timebase++; + } + + printf("\nTimebase: %lu SampleInterval: %ldnS oversample: %hd\n", + timebase, timeInterval, oversample); + + /* Start it collecting, then wait for completion*/ + g_ready = FALSE; + status = ps2000aRunBlock(unit->handle, 0, sampleCount, timebase, + oversample, &timeIndisposed, 0, CallBackBlock, NULL); + printf(status ? "BlockDataHandler:ps2000aRunBlock ------ 0x%08lx \n" : "", + status); + + printf("Waiting for trigger...Press a key to abort\n"); + + while (!g_ready && !_kbhit()) + { + Sleep(0); + } + + if (g_ready) + { + status = ps2000aGetValues(unit->handle, 0, + (uint32_t*) &sampleCount, 1, PS2000A_RATIO_MODE_NONE, 0, + NULL); + printf( + status + ? "BlockDataHandler:ps2000aGetValues ------ 0x%08lx \n" + : "", status); + + /* Print out the first 10 readings, converting the readings to mV if required */ + printf("%s\n", text); + + if (mode == ANALOGUE || mode == MIXED) // if we're doing analogue or MIXED + { + printf("Channels are in (%s)\n", (scaleVoltages) + ? ("mV") + : ("ADC Counts")); + + for (j = 0; j < unit->channelCount; j++) + { + if (unit->channelSettings[j].enabled) + printf("Channel%c:\t", 'A' + j); + } + } + + if (mode == DIGITAL || mode == MIXED) // if we're doing digital or MIXED + printf("Digital"); + + printf("\n"); + + for (i = offset; i < offset + 10; i++) + { + if (mode == ANALOGUE || mode == MIXED) // if we're doing analogue or MIXED + { + for (j = 0; j < unit->channelCount; j++) + { + if (unit->channelSettings[j].enabled) + { + printf(" %6d ", + scaleVoltages ? adc_to_mv(buffers[j * 2][i], + unit->channelSettings[PS2000A_CHANNEL_A + + j].range, unit) // If scaleVoltages, print mV value + : buffers[j * 2][i]); // else print ADC Count + } + } + } + if (mode == DIGITAL || mode == MIXED) // if we're doing digital or MIXED + { + digiValue = 0x00ff & digiBuffer[1][i]; + digiValue <<= 8; + digiValue |= digiBuffer[0][i]; + printf("0x%04X", digiValue); + } + printf("\n"); + } + + if (mode == ANALOGUE || mode == MIXED) // if we're doing analogue or MIXED + { + sampleCount = min(sampleCount, BUFFER_SIZE); + + fopen_s(&fp, BlockFile, "w"); + if (fp != NULL) + { + fprintf(fp, "Block Data log\n\n"); + fprintf( + fp, + "Results shown for each of the %d Channels are......\n", + unit->channelCount); + fprintf( + fp, + "Maximum Aggregated value ADC Count & mV, Minimum Aggregated value ADC Count & mV\n\n"); + + fprintf(fp, "Time "); + for (i = 0; i < unit->channelCount; i++) + fprintf(fp, " Ch Max ADC Max mV Min ADC Min mV "); + fprintf(fp, "\n"); + + for (i = 0; i < sampleCount; i++) + { + fprintf(fp, "%5lld ", g_times[0] + (int64_t) (i + * timeInterval)); + for (j = 0; j < unit->channelCount; j++) + { + if (unit->channelSettings[j].enabled) + { + fprintf( + fp, + "Ch%C %5d = %+5dmV, %5d = %+5dmV ", + (char) ('A' + j), + buffers[j * 2][i], + adc_to_mv( + buffers[j * 2][i], + unit->channelSettings[PS2000A_CHANNEL_A + + j].range, unit), + buffers[j * 2 + 1][i], + adc_to_mv( + buffers[j * 2 + 1][i], + unit->channelSettings[PS2000A_CHANNEL_A + + j].range, unit)); + } + } + fprintf(fp, "\n"); + } + } + else + { + printf("Cannot open the file block.txt for writing.\n" + "Please ensure that you have permission to access.\n"); + } + } + } + else + { + printf("data collection aborted\n"); + _getch(); + } + + status = ps2000aStop(unit->handle); + printf(status ? "BlockDataHandler:ps2000aStop ------ 0x%08lx \n" : "", + status); + + if (fp != NULL) + fclose(fp); + + if (mode == ANALOGUE || mode == MIXED) // Only if we allocated these buffers + { + for (i = 0; i < unit->channelCount * 2; i++) + { + free(buffers[i]); + } + } + + if (mode == DIGITAL || mode == MIXED) // Only if we allocated these buffers + { + for (i = 0; i < unit->digitalPorts; i++) + { + free(digiBuffer[i]); + } + } + ClearDataBuffers(unit); +} + +/**************************************************************************** + * Stream Data Handler + * - Used by the two stream data examples - untriggered and triggered + * Inputs: + * - unit - the unit to sample on + * - preTrigger - the number of samples in the pre-trigger phase + * (0 if no trigger has been set) + ***************************************************************************/ +void StreamDataHandler(UNIT * unit, uint32_t preTrigger, MODE mode) +{ + int64_t i, j; + uint32_t sampleCount = BUFFER_SIZE * 10; /* *10 is to make sure buffer large enough */ + FILE * fp = NULL; + int16_t * buffers[PS2000A_MAX_CHANNEL_BUFFERS]; + int16_t * digiBuffers[PS2000A_MAX_DIGITAL_PORTS]; + PICO_STATUS status; + uint32_t sampleInterval; + int32_t index = 0; + int32_t totalSamples; + uint32_t postTrigger; + int16_t autostop; + uint32_t downsampleRatio; + uint32_t triggeredAt = 0; + int32_t bit; + uint16_t portValue, portValueOR, portValueAND; + PS2000A_TIME_UNITS timeUnits; + PS2000A_RATIO_MODE ratioMode; + + if (mode == ANALOGUE) // Analogue + { + for (i = 0; i < unit->channelCount; i++) + { + buffers[i * 2] = (int16_t*) malloc(sampleCount * sizeof(int16_t)); + buffers[i * 2 + 1] = (int16_t*) malloc(sampleCount * sizeof(int16_t)); + status = ps2000aSetDataBuffers(unit->handle, (int16_t) i, buffers[i + * 2], buffers[i * 2 + 1], sampleCount, 0, + PS2000A_RATIO_MODE_AGGREGATE); + + printf( + status + ? "StreamDataHandler:ps2000aSetDataBuffers(channel %ld) ------ 0x%08lx \n" + : "", i, status); + } + + downsampleRatio = 1000; + timeUnits = PS2000A_US; + sampleInterval = 1; + ratioMode = PS2000A_RATIO_MODE_AGGREGATE; + postTrigger = 1000000; + autostop = TRUE; + } + + if (mode == AGGREGATED) // (MSO Only) AGGREGATED + { + for (i = 0; i < unit->digitalPorts; i++) + { + + digiBuffers[i * 2] = (int16_t*) malloc(sampleCount * sizeof(int16_t)); + digiBuffers[i * 2 + 1] = (int16_t*) malloc(sampleCount + * sizeof(int16_t)); + status = ps2000aSetDataBuffers(unit->handle, (PS2000A_CHANNEL) (i + + PS2000A_DIGITAL_PORT0), digiBuffers[i * 2], digiBuffers[i + * 2 + 1], sampleCount, 0, PS2000A_RATIO_MODE_AGGREGATE); + + printf( + status + ? "StreamDataHandler:ps2000aSetDataBuffer(channel %ld) ------ 0x%08lx \n" + : "", i, status); + } + + downsampleRatio = 10; + timeUnits = PS2000A_MS; + sampleInterval = 10; + ratioMode = PS2000A_RATIO_MODE_AGGREGATE; + postTrigger = 10; + autostop = FALSE; + } + + if (mode == DIGITAL) // (MSO Only) Digital + { + for (i = 0; i < unit->digitalPorts; i++) + { + digiBuffers[i] = (int16_t*) malloc(sampleCount * sizeof(int16_t)); + status = ps2000aSetDataBuffer(unit->handle, (PS2000A_CHANNEL) (i + + PS2000A_DIGITAL_PORT0), digiBuffers[i], sampleCount, 0, + PS2000A_RATIO_MODE_NONE); + + printf( + status + ? "StreamDataHandler:ps2000aSetDataBuffer(channel %ld) ------ 0x%08lx \n" + : "", i, status); + } + + downsampleRatio = 1; + timeUnits = PS2000A_MS; + sampleInterval = 10; + ratioMode = PS2000A_RATIO_MODE_NONE; + postTrigger = 10; + autostop = FALSE; + } + + if (autostop) + { + printf("\nStreaming Data for %lu samples", postTrigger + / downsampleRatio); + if (preTrigger) // we pass 0 for preTrigger if we're not setting up a trigger + printf( + " after the trigger occurs\nNote: %lu Pre Trigger samples before Trigger arms\n\n", + preTrigger / downsampleRatio); + else + printf("\n\n"); + } + else + printf("\nStreaming Data continually\n\n"); + + g_autoStopped = FALSE; + + status = ps2000aRunStreaming(unit->handle, &sampleInterval, timeUnits, + preTrigger, postTrigger - preTrigger, autostop, downsampleRatio, + ratioMode, sampleCount); + + printf("Streaming data...Press a key to stop\n"); + + if (mode == ANALOGUE) + { + fopen_s(&fp, StreamFile, "w"); + + if (fp != NULL) + { + fprintf(fp, "For each of the %d Channels, results shown are....\n", + unit->channelCount); + fprintf( + fp, + "Maximum Aggregated value ADC Count & mV, Minimum Aggregated value ADC Count & mV\n\n"); + + for (i = 0; i < unit->channelCount; i++) + fprintf(fp, " Max ADC Max mV Min ADC Min mV"); + fprintf(fp, "\n"); + } + } + + totalSamples = 0; + while (!_kbhit() && !g_autoStopped && !g_overflow) + { + /* Poll until data is received. Until then, GetStreamingLatestValues wont call the callback */ + Sleep(100); + g_ready = FALSE; + + status = ps2000aGetStreamingLatestValues(unit->handle, + CallBackStreaming, NULL); + index++; + + if (g_ready && g_sampleCount > 0) /* can be ready and have no data, if autoStop has fired */ + { + if (g_trig) + triggeredAt = totalSamples += g_trigAt; // calculate where the trigger occurred in the total samples collected + + totalSamples += g_sampleCount; + printf( + "\nCollected %3li samples, index = %5lu, Total: %6d samples ", + g_sampleCount, g_startIndex, totalSamples); + + if (g_trig) + printf("Trig. at index %lu", triggeredAt); // show where trigger occurred + + + for (i = g_startIndex; i < (int64_t) (g_startIndex + g_sampleCount); i++) + { + if (mode == ANALOGUE) + { + if (fp != NULL) + { + for (j = 0; j < unit->channelCount; j++) + { + if (unit->channelSettings[j].enabled) + { + fprintf( + fp, + "Ch%C %5d = %+5dmV, %5d = %+5dmV ", + (char) ('A' + j), + buffers[j * 2][i], + adc_to_mv( + buffers[j * 2][i], + unit->channelSettings[PS2000A_CHANNEL_A + + j].range, unit), + buffers[j * 2 + 1][i], + adc_to_mv( + buffers[j * 2 + 1][i], + unit->channelSettings[PS2000A_CHANNEL_A + + j].range, unit)); + } + } + fprintf(fp, "\n"); + } + else + printf("Cannot open the file stream.txt for writing.\n"); + + } + + if (mode == DIGITAL) + { + portValue = 0x00ff & digiBuffers[1][i]; + portValue <<= 8; + portValue |= 0x00ff & digiBuffers[0][i]; + + printf("\nIndex=%04lu: Value = 0x%04X = ", i, portValue); + + for (bit = 0; bit < 16; bit++) + { + printf((0x8000 >> bit) & portValue ? "1 " : "0 "); + } + } + + if (mode == AGGREGATED) + { + portValueOR = 0x00ff & digiBuffers[2][i]; + portValueOR <<= 8; + portValueOR |= 0x00ff & digiBuffers[0][i]; + + portValueAND = 0x00ff & digiBuffers[3][i]; + portValueAND <<= 8; + portValueAND |= 0x00ff & digiBuffers[1][i]; + + printf( + "\nIndex=%04lu: Bitwise OR of last %ld readings = 0x%04X ", + i, downsampleRatio, portValueOR); + printf( + "\nIndex=%04lu: Bitwise AND of last %ld readings = 0x%04X ", + i, downsampleRatio, portValueAND); + } + } + } + } + + ps2000aStop(unit->handle); + + if (!g_autoStopped) + { + printf("\ndata collection aborted\n"); + _getch(); + } + + if (g_overflow) + { + printf( + "\nStreaming overflow. Not able to keep up with streaming data rate\n"); + } + + if (fp != NULL) + fclose(fp); + + if (mode == ANALOGUE) // Only if we allocated these buffers + { + for (i = 0; i < unit->channelCount * 2; i++) + { + free(buffers[i]); + } + } + + if (mode == DIGITAL) // Only if we allocated these buffers + { + for (i = 0; i < unit->digitalPorts; i++) + { + free(digiBuffers[i]); + } + + } + + if (mode == AGGREGATED) // Only if we allocated these buffers + { + for (i = 0; i < unit->digitalPorts * 2; i++) + { + free(digiBuffers[i]); + } + } + + ClearDataBuffers(unit); +} + +/**************************************************************************** + * SetTrigger + * + * Parameters + * - *unit - pointer to the UNIT structure + * - *channelProperties - pointer to the PS2000A_TRIGGER_CHANNEL_PROPERTIES structure + * - nChannelProperties - the number of PS2000A_TRIGGER_CHANNEL_PROPERTIES elements in channelProperties + * - *triggerConditions - pointer to the PS2000A_TRIGGER_CONDITIONS structure + * - nTriggerConditions - the number of PS2000A_TRIGGER_CONDITIONS elements in triggerConditions + * - *directions - pointer to the TRIGGER_DIRECTIONS structure + * - *pwq - pointer to the pwq (Pulse Width Qualifier) structure + * - delay - Delay time between trigger & first sample + * - auxOutputEnable - Not used + * - autoTriggerMs - timeout period if no trigger occurs + * - *digitalDirections - pointer to the PS2000A_DIGITAL_CHANNEL_DIRECTIONS structure + * - nDigitalDirections - the number of PS2000A_DIGITAL_CHANNEL_DIRECTIONS elements in digitalDirections + * + * Returns - PICO_STATUS - to show success or if an error occurred + * + ***************************************************************************/ +PICO_STATUS SetTrigger(UNIT * unit, + PS2000A_TRIGGER_CHANNEL_PROPERTIES * channelProperties, + int16_t nChannelProperties, + PS2000A_TRIGGER_CONDITIONS * triggerConditions, + int16_t nTriggerConditions, TRIGGER_DIRECTIONS * directions, PWQ * pwq, + uint32_t delay, int16_t auxOutputEnabled, int64_t autoTriggerMs, + PS2000A_DIGITAL_CHANNEL_DIRECTIONS * digitalDirections, + int16_t nDigitalDirections) +{ + PICO_STATUS status; + + if ((status = ps2000aSetTriggerChannelProperties(unit->handle, + channelProperties, nChannelProperties, auxOutputEnabled, + autoTriggerMs)) != PICO_OK) + { + printf( + "SetTrigger:ps2000aSetTriggerChannelProperties ------ Ox%8lx \n", + status); + return status; + } + + if ((status = ps2000aSetTriggerChannelConditions(unit->handle, + triggerConditions, nTriggerConditions)) != PICO_OK) + { + printf( + "SetTrigger:ps2000aSetTriggerChannelConditions ------ 0x%8lx \n", + status); + return status; + } + + if ((status = ps2000aSetTriggerChannelDirections(unit->handle, + directions->channelA, directions->channelB, directions->channelC, + directions->channelD, directions->ext, directions->aux)) != PICO_OK) + { + printf( + "SetTrigger:ps2000aSetTriggerChannelDirections ------ 0x%08lx \n", + status); + return status; + } + + if ((status = ps2000aSetTriggerDelay(unit->handle, delay)) != PICO_OK) + { + printf("SetTrigger:ps2000aSetTriggerDelay ------ 0x%08lx \n", status); + return status; + } + + if ((status + = ps2000aSetPulseWidthQualifier(unit->handle, pwq->conditions, + pwq->nConditions, pwq->direction, pwq->lower, pwq->upper, + pwq->type)) != PICO_OK) + { + printf("SetTrigger:ps2000aSetPulseWidthQualifier ------ 0x%08lx \n", + status); + return status; + } + + if (unit->digitalPorts) // ps2000aSetTriggerDigitalPortProperties function only applies to MSO + { + if ((status = ps2000aSetTriggerDigitalPortProperties(unit->handle, + digitalDirections, nDigitalDirections)) != PICO_OK) + { + printf( + "SetTrigger:ps2000aSetTriggerDigitalPortProperties ------ 0x%08lx \n", + status); + return status; + } + } + return status; +} + +/**************************************************************************** + * CollectBlockImmediate + * this function demonstrates how to collect a single block of data + * from the unit (start collecting immediately) + ****************************************************************************/ +void CollectBlockImmediate(UNIT * unit) +{ + PWQ pulseWidth; + TRIGGER_DIRECTIONS directions; + + memset(&directions, 0, sizeof(TRIGGER_DIRECTIONS)); + memset(&pulseWidth, 0, sizeof(PWQ)); + + printf("Collect block immediate\n"); + printf("Data is written to disk file (%s)\n", BlockFile); + printf("Press a key to start...\n"); + _getch(); + + SetDefaults(unit); + + /* Trigger disabled */ + SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0); + + BlockDataHandler(unit, "First 10 readings\n", 0, ANALOGUE); +} + +/**************************************************************************** + * CollectBlockEts + * this function demonstrates how to collect a block of + * data using equivalent time sampling (ETS). + ****************************************************************************/ +void CollectBlockEts(UNIT * unit) +{ + PICO_STATUS status; + int64_t ets_sampletime; + int16_t triggerVoltage = mv_to_adc(1000, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit); + uint32_t delay = 0; + struct tPwq pulseWidth; + struct tTriggerDirections directions; + + PS2000A_TRIGGER_CHANNEL_PROPERTIES sourceDetails = + { triggerVoltage, 256 * 10, triggerVoltage, 256 * 10, PS2000A_CHANNEL_A, + PS2000A_LEVEL }; + + PS2000A_TRIGGER_CONDITIONS conditions = + { PS2000A_CONDITION_TRUE, PS2000A_CONDITION_DONT_CARE, + PS2000A_CONDITION_DONT_CARE, PS2000A_CONDITION_DONT_CARE, + PS2000A_CONDITION_DONT_CARE, PS2000A_CONDITION_DONT_CARE, + PS2000A_CONDITION_DONT_CARE, PS2000A_CONDITION_DONT_CARE }; + + memset(&pulseWidth, 0, sizeof(struct tPwq)); + memset(&directions, 0, sizeof(struct tTriggerDirections)); + directions.channelA = PS2000A_RISING; + + printf("Collect ETS block...\n"); + printf("Collects when value rises past %d", + scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value + : sourceDetails.thresholdUpper); // else print ADC Count + printf(scaleVoltages ? "mV\n" : "ADC Counts\n"); + printf("Press a key to start...\n"); + _getch(); + + SetDefaults(unit); + + //Trigger enabled + //Rising edge + //Threshold = 1000mV + status = SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions, + &pulseWidth, delay, 0, 0, 0, 0); + + if ((status = ps2000aSetEts(unit->handle, PS2000A_ETS_FAST, 20, 4, + &ets_sampletime)) != PICO_OK) + printf("CollectBlockEts:ps2000aSetEts ------ 0x%08lx \n", status); + + printf("ETS Sample Time is: %ld\n", ets_sampletime); + + BlockDataHandler(unit, "Ten readings after trigger\n", + BUFFER_SIZE / 10 - 5, ANALOGUE); // 10% of data is pre-trigger +} + +/**************************************************************************** + * CollectBlockTriggered + * this function demonstrates how to collect a single block of data from the + * unit, when a trigger event occurs. + ****************************************************************************/ +void CollectBlockTriggered(UNIT * unit) +{ + int16_t triggerVoltage = mv_to_adc(1000, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit); + + PS2000A_TRIGGER_CHANNEL_PROPERTIES sourceDetails = + { triggerVoltage, 256 * 10, triggerVoltage, 256 * 10, PS2000A_CHANNEL_A, + PS2000A_LEVEL }; + + PS2000A_TRIGGER_CONDITIONS conditions = + { PS2000A_CONDITION_TRUE, // Channel A + PS2000A_CONDITION_DONT_CARE, // Channel B + PS2000A_CONDITION_DONT_CARE, // Channel C + PS2000A_CONDITION_DONT_CARE, // Channel D + PS2000A_CONDITION_DONT_CARE, // external + PS2000A_CONDITION_DONT_CARE, // aux + PS2000A_CONDITION_DONT_CARE, // PWQ + PS2000A_CONDITION_DONT_CARE }; // digital + + + TRIGGER_DIRECTIONS directions = + { PS2000A_RISING, // Channel A + PS2000A_NONE, // Channel B + PS2000A_NONE, // Channel C + PS2000A_NONE, // Channel D + PS2000A_NONE, // ext + PS2000A_NONE }; // aux + + PWQ pulseWidth; + memset(&pulseWidth, 0, sizeof(PWQ)); + + printf("Collect block triggered\n"); + printf("Data is written to disk file (%s)\n", BlockFile); + printf("Collects when value rises past %d", + scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value + : sourceDetails.thresholdUpper); // else print ADC Count + printf(scaleVoltages ? "mV\n" : "ADC Counts\n"); + + printf("Press a key to start...\n"); + _getch(); + + SetDefaults(unit); + + /* Trigger enabled + * Rising edge + * Threshold = 1000mV */ + SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions, + &pulseWidth, 0, 0, 0, 0, 0); + + BlockDataHandler(unit, "Ten readings after trigger\n", 0, ANALOGUE); +} + +/**************************************************************************** + * CollectRapidBlock + * this function demonstrates how to collect a set of captures using + * rapid block mode. + ****************************************************************************/ +void CollectRapidBlock(UNIT * unit) +{ + uint16_t nCaptures; + int64_t nMaxSamples; + uint32_t nSamples = 1000; + int64_t timeIndisposed; + int16_t capture, channel; + int16_t ***rapidBuffers; + int16_t *overflow; + PICO_STATUS status; + int16_t i; + uint32_t nCompletedCaptures; + + int16_t triggerVoltage = mv_to_adc(100, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit); + + struct tPS2000ATriggerChannelProperties sourceDetails = + { triggerVoltage, 256 * 10, triggerVoltage, 256 * 10, PS2000A_CHANNEL_A, + PS2000A_LEVEL }; + + struct tPS2000ATriggerConditions conditions = + { PS2000A_CONDITION_TRUE, // Channel A + PS2000A_CONDITION_DONT_CARE, // Channel B + PS2000A_CONDITION_DONT_CARE, // Channel C + PS2000A_CONDITION_DONT_CARE, // Channel D + PS2000A_CONDITION_DONT_CARE, // external + PS2000A_CONDITION_DONT_CARE, // aux + PS2000A_CONDITION_DONT_CARE, // PWQ + PS2000A_CONDITION_DONT_CARE }; // digital + + struct tPwq pulseWidth; + + struct tTriggerDirections directions = + { PS2000A_RISING, // Channel A + PS2000A_NONE, // Channel B + PS2000A_NONE, // Channel C + PS2000A_NONE, // Channel D + PS2000A_NONE, // ext + PS2000A_NONE }; // aux + + memset(&pulseWidth, 0, sizeof(struct tPwq)); + + printf("Collect rapid block triggered...\n"); + printf("Collects when value rises past %d", + scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value + : sourceDetails.thresholdUpper); // else print ADC Count + printf(scaleVoltages ? "mV\n" : "ADC Counts\n"); + printf("Press any key to abort\n"); + + SetDefaults(unit); + + // Trigger enabled + SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions, + &pulseWidth, 0, 0, 0, 0, 0); + + //Set the number of captures + nCaptures = 10; + + //Segment the memory + status = ps2000aMemorySegments(unit->handle, nCaptures, &nMaxSamples); + + //Set the number of captures + status = ps2000aSetNoOfCaptures(unit->handle, nCaptures); + + //Run + timebase = 160; //1 MS/s + status = ps2000aRunBlock(unit->handle, 0, nSamples, timebase, 1, + &timeIndisposed, 0, CallBackBlock, NULL); + + //Wait until data ready + g_ready = 0; + while (!g_ready && !_kbhit()) + { + Sleep(0); + } + + if (!g_ready) + { + _getch(); + status = ps2000aStop(unit->handle); + status = ps2000aGetNoOfCaptures(unit->handle, &nCompletedCaptures); + printf("Rapid capture aborted. %lu complete blocks were captured\n", + nCompletedCaptures); + printf("\nPress any key...\n\n"); + _getch(); + + if (nCompletedCaptures == 0) + return; + + //Only display the blocks that were captured + nCaptures = (uint16_t) nCompletedCaptures; + } + + //Allocate memory + rapidBuffers = calloc(unit->channelCount, sizeof(int16_t*)); + overflow = calloc(unit->channelCount * nCaptures, sizeof(int16_t)); + + for (channel = 0; channel < unit->channelCount; channel++) + { + rapidBuffers[channel] = calloc(nCaptures, sizeof(int16_t*)); + } + + for (channel = 0; channel < unit->channelCount; channel++) + { + if (unit->channelSettings[channel].enabled) + { + for (capture = 0; capture < nCaptures; capture++) + { + rapidBuffers[channel][capture] + = calloc(nSamples, sizeof(int16_t)); + } + } + } + + for (channel = 0; channel < unit->channelCount; channel++) + { + if (unit->channelSettings[channel].enabled) + { + for (capture = 0; capture < nCaptures; capture++) + { + status = ps2000aSetDataBuffer(unit->handle, channel, + rapidBuffers[channel][capture], nSamples, capture, + PS2000A_RATIO_MODE_NONE); + } + } + } + + //Get data + status = ps2000aGetValuesBulk(unit->handle, &nSamples, 0, nCaptures - 1, 1, + PS2000A_RATIO_MODE_NONE, overflow); + + //Stop + status = ps2000aStop(unit->handle); + + //print first 10 samples from each capture + for (capture = 0; capture < nCaptures; capture++) + { + printf("\nCapture %d\n", capture + 1); + for (channel = 0; channel < unit->channelCount; channel++) + { + printf("Channel %c\t", 'A' + channel); + } + printf("\n"); + + for (i = 0; i < 10; i++) + { + for (channel = 0; channel < unit->channelCount; channel++) + { + if (unit->channelSettings[channel].enabled) + { + printf("%d\t\t", rapidBuffers[channel][capture][i]); + } + } + printf("\n"); + } + } + + //Free memory + free(overflow); + + for (channel = 0; channel < unit->channelCount; channel++) + { + if (unit->channelSettings[channel].enabled) + { + for (capture = 0; capture < nCaptures; capture++) + { + free(rapidBuffers[channel][capture]); + } + } + } + + for (channel = 0; channel < unit->channelCount; channel++) + { + free(rapidBuffers[channel]); + } + free(rapidBuffers); +} + +/**************************************************************************** +* Initialise unit' structure with Variant specific defaults +****************************************************************************/ +void set_info(UNIT * unit) +{ + int16_t r = 0; + char line [8] = {0}; + int32_t variant; + PICO_STATUS status = PICO_OK; + + if (unit->handle) + { + // info = 3 - PICO_VARIANT_INFO + ps2000aGetUnitInfo(unit->handle, line, sizeof (line), &r, 3); + variant = atoi(line); + memcpy(&(unit->modelString),line,sizeof(unit->modelString)==7?7:sizeof(unit->modelString)); + //To identify variants..... + + if (strlen(line) == 5) // A variant unit + { + line[4] = toupper(line[4]); + + if (line[4] == 'A') // i.e 2207A -> 0xA207 + variant += 0x9968; + } else + variant += 0x1968; // 2206 -> 0x2206 + + if (strlen(line) == 7) + { + line[4] = toupper(line[4]); + line[5] = toupper(line[5]); + line[6] = toupper(line[6]); + + if(strcmp(line+4, "MSO") == 0) + variant += 0xC000; // 2205MSO -> 0xE205 + } + + // info = 4 - PICO_BATCH_AND_SERIAL + ps2000aGetUnitInfo(unit->handle, unit->serial, sizeof (unit->serial), &r, 4); + } + + switch (variant) + { + + case MODEL_PS2205MSO: + unit->model = variant; + unit->signalGenerator = TRUE; + unit->ETS = FALSE; + unit->firstRange = PS2000A_50MV; + unit->lastRange = PS2000A_20V; + unit->channelCount = DUAL_SCOPE; + unit->digitalPorts = 2; + break; + + case MODEL_PS2206: + unit->model = variant; + unit->signalGenerator = TRUE; + unit->ETS = FALSE; + unit->firstRange = PS2000A_50MV; + unit->lastRange = PS2000A_20V; + unit->channelCount = DUAL_SCOPE; + unit->digitalPorts = 0; + break; + + case MODEL_PS2207: + unit->model = variant; + unit->signalGenerator = TRUE; + unit->ETS = FALSE; + unit->firstRange = PS2000A_50MV; + unit->lastRange = PS2000A_20V; + unit->channelCount = DUAL_SCOPE; + unit->digitalPorts = 0; + break; + + case MODEL_PS2208: + unit->model = variant; + unit->signalGenerator = TRUE; + unit->ETS = TRUE; + unit->firstRange = PS2000A_50MV; + unit->lastRange = PS2000A_20V; + unit->channelCount = DUAL_SCOPE; + unit->digitalPorts = 0; + break; + + case MODEL_PS2206A: + unit->model = variant; + unit->signalGenerator = TRUE; + unit->ETS = FALSE; + unit->firstRange = PS2000A_50MV; + unit->lastRange = PS2000A_20V; + unit->channelCount = DUAL_SCOPE; + unit->digitalPorts = 0; + break; + + case MODEL_PS2207A: + unit->model = variant; + unit->signalGenerator = TRUE; + unit->ETS = FALSE; + unit->firstRange = PS2000A_50MV; + unit->lastRange = PS2000A_20V; + unit->channelCount = DUAL_SCOPE; + unit->digitalPorts = 0; + break; + + case MODEL_PS2208A: + unit->model = variant; + unit->signalGenerator = TRUE; + unit->ETS = TRUE; + unit->firstRange = PS2000A_50MV; + unit->lastRange = PS2000A_20V; + unit->channelCount = DUAL_SCOPE; + unit->digitalPorts = 0; + break; + + default: + break; + } +} + +/**************************************************************************** + * Select input voltage ranges for channels + ****************************************************************************/ +void SetVoltages(UNIT * unit) +{ + int32_t i, ch; + int32_t count = 0; + + /* See what ranges are available... */ + for (i = unit->firstRange; i <= unit->lastRange; i++) + { + printf("%d -> %d mV\n", i, inputRanges[i]); + } + + do + { + /* Ask the user to select a range */ + printf("Specify voltage range (%d..%d)\n", unit->firstRange, + unit->lastRange); + printf("99 - switches channel off\n"); + for (ch = 0; ch < unit->channelCount; ch++) + { + printf("\n"); + do + { + printf("Channel %c: ", 'A' + ch); + fflush(stdin); + scanf_s("%hd", &unit->channelSettings[ch].range); + } while (unit->channelSettings[ch].range != 99 + && (unit->channelSettings[ch].range < unit->firstRange + || unit->channelSettings[ch].range + > unit->lastRange)); + + if (unit->channelSettings[ch].range != 99) + { + printf(" - %d mV\n", + inputRanges[unit->channelSettings[ch].range]); + unit->channelSettings[ch].enabled = TRUE; + count++; + } + else + { + printf("Channel Switched off\n"); + unit->channelSettings[ch].enabled = FALSE; + unit->channelSettings[ch].range = PS2000A_MAX_RANGES - 1; + } + } + printf(count == 0 + ? "\n** At least 1 channel must be enabled **\n\n" + : ""); + } while (count == 0); // must have at least one channel enabled + + SetDefaults(unit); // Put these changes into effect +} + +/**************************************************************************** + * + * Select timebase, set oversample to on and time units as nano seconds + * + ****************************************************************************/ +void SetTimebase(UNIT *unit) +{ + int64_t timeInterval; + int64_t maxSamples; + + printf("Specify desired timebase: "); + fflush(stdin); + scanf_s("%lu", &timebase); + + while (ps2000aGetTimebase(unit->handle, timebase, BUFFER_SIZE, + &timeInterval, 1, &maxSamples, 0)) + { + timebase++; // Increase timebase if the one specified can't be used. + } + + printf("Timebase %lu used = %ld ns\n", timebase, timeInterval); + oversample = TRUE; +} + +/**************************************************************************** + * Sets the signal generator + * - allows user to set frequency and waveform + * - allows for custom waveform (values -32768..32767) of up to 8192 samples int64_t + ***************************************************************************/ +void SetSignalGenerator(UNIT *unit) +{ + PICO_STATUS status; + int16_t waveform; + int64_t frequency; + char fileName[128]; + FILE * fp = NULL; + int16_t arbitraryWaveform[8192]; + int16_t waveformSize = 0; + uint32_t pkpk = 1000000; + int64_t offset = 0; + char ch; + int16_t choice; + + memset(&arbitraryWaveform, 0, 8192); + + while (_kbhit()) // use up keypress + _getch(); + + do + { + printf("\nSignal Generator\n================\n"); + printf("0 - SINE 1 - SQUARE\n"); + printf("2 - TRIANGLE 3 - DC VOLTAGE\n"); + printf("4 - RAMP UP 5 - RAMP DOWN\n"); + printf("6 - SINC 7 - GAUSSIAN\n"); + printf("8 - HALF SINE A - AWG WAVEFORM\n"); + printf("F - SigGen Off\n\n"); + + ch = _getch(); + + if (ch >= '0' && ch <= '9') + choice = ch - '0'; + else + ch = toupper(ch); + } while (ch != 'A' && ch != 'F' && (ch < '0' || ch > '8')); + + if (ch == 'F') // If we're going to turn off siggen + { + printf("Signal generator Off\n"); + waveform = 8; // DC Voltage + pkpk = 0; // 0V + waveformSize = 0; + } + else if (ch == 'A') // Set the AWG + { + waveformSize = 0; + + printf("Select a waveform file to load: "); + scanf_s("%s", fileName, 128); + if (fopen_s(&fp, fileName, "r") == 0) + { // Having opened file, read in data - one number per line (at most 8192 lines), with values in (-32768 to 32767) + while (EOF != fscanf_s(fp, "%hi", + (arbitraryWaveform + waveformSize)) && waveformSize++ + < 8191) + ; + fclose(fp); + printf("File successfully loaded\n"); + } + else + { + printf("Invalid filename\n"); + return; + } + } + else // Set one of the built in waveforms + { + switch (choice) + { + case 0: + waveform = PS2000A_SINE; + break; + + case 1: + waveform = PS2000A_SQUARE; + break; + + case 2: + waveform = PS2000A_TRIANGLE; + break; + + case 3: + waveform = PS2000A_DC_VOLTAGE; + do + { + printf("\nEnter offset in uV: (0 to 2500000)\n"); // Ask user to enter DC offset level; + scanf_s("%llu", &offset); + } while (offset < 0 || offset > 10000000); + break; + + case 4: + waveform = PS2000A_RAMP_UP; + break; + + case 5: + waveform = PS2000A_RAMP_DOWN; + break; + + case 6: + waveform = PS2000A_SINC; + break; + + case 7: + waveform = PS2000A_GAUSSIAN; + break; + + case 8: + waveform = PS2000A_HALF_SINE; + break; + + default: + waveform = PS2000A_SINE; + break; + } + } + + if (waveform < 8 || ch == 'A') // Find out frequency if required + { + do + { + printf("\nEnter frequency in Hz: (1 to 1000000)\n"); // Ask user to enter signal frequency; + scanf_s("%lu", &frequency); + } while (frequency <= 0 || frequency > 1000000); + } + + if (waveformSize > 0) + { + double delta = ((1.0 * frequency * waveformSize) / 8192.0) + * 4294967296.0 * 5e-8; // delta >= 10 + + status = ps2000aSetSigGenArbitrary(unit->handle, 0, 1000000, + (uint32_t) delta, (uint32_t) delta, 0, 0, + arbitraryWaveform, waveformSize, 0, 0, PS2000A_SINGLE, 0, 0, + PS2000A_SIGGEN_RISING, PS2000A_SIGGEN_NONE, 0); + + printf(status + ? "\nps2000aSetSigGenArbitrary: Status Error 0x%x \n" + : "", (uint32_t) status); // If status != 0, show the error + } + else + { + status + = ps2000aSetSigGenBuiltIn(unit->handle, offset, pkpk, waveform, + (float) frequency, (float) frequency, 0, 0, 0, 0, 0, 0, + 0, 0, 0); + printf(status ? "\nps2000aSetSigGenBuiltIn: Status Error 0x%x \n" : "", + (uint32_t) status); // If status != 0, show the error + } +} + +/**************************************************************************** + * CollectStreamingImmediate + * this function demonstrates how to collect a stream of data + * from the unit (start collecting immediately) + ***************************************************************************/ +void CollectStreamingImmediate(UNIT * unit) +{ + struct tPwq pulseWidth; + struct tTriggerDirections directions; + + memset(&pulseWidth, 0, sizeof(struct tPwq)); + memset(&directions, 0, sizeof(struct tTriggerDirections)); + + SetDefaults(unit); + + printf("Collect streaming...\n"); + printf("Data is written to disk file (%s)\n", StreamFile); + printf("Press a key to start...\n"); + _getch(); + + /* Trigger disabled */ + SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0); + + StreamDataHandler(unit, 0, ANALOGUE); +} + +/**************************************************************************** + * CollectStreamingTriggered + * this function demonstrates how to collect a stream of data + * from the unit (start collecting on trigger) + ***************************************************************************/ +void CollectStreamingTriggered(UNIT * unit) +{ + int16_t triggerVoltage = mv_to_adc(1000, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit); // ChannelInfo stores ADC counts + struct tPwq pulseWidth; + + struct tPS2000ATriggerChannelProperties sourceDetails = + { triggerVoltage, 256 * 10, triggerVoltage, 256 * 10, PS2000A_CHANNEL_A, + PS2000A_LEVEL }; + + struct tPS2000ATriggerConditions conditions = + { PS2000A_CONDITION_TRUE, // Channel A + PS2000A_CONDITION_DONT_CARE, // Channel B + PS2000A_CONDITION_DONT_CARE, // Channel C + PS2000A_CONDITION_DONT_CARE, // Channel D + PS2000A_CONDITION_DONT_CARE, // Exteranl + PS2000A_CONDITION_DONT_CARE, // aux + PS2000A_CONDITION_DONT_CARE, // PWQ + PS2000A_CONDITION_DONT_CARE }; // digital + + struct tTriggerDirections directions = + { PS2000A_RISING, // Channel A + PS2000A_NONE, // Channel B + PS2000A_NONE, // Channel C + PS2000A_NONE, // Channel D + PS2000A_NONE, // External + PS2000A_NONE }; // Aux + + memset(&pulseWidth, 0, sizeof(struct tPwq)); + + printf("Collect streaming triggered...\n"); + printf("Data is written to disk file (%s)\n", StreamFile); + printf("Indicates when value rises past %d", + scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value + : sourceDetails.thresholdUpper); // else print ADC Count + printf(scaleVoltages ? "mV\n" : "ADC Counts\n"); + printf("Press a key to start...\n"); + _getch(); + SetDefaults(unit); + + /* Trigger enabled + * Rising edge + * Threshold = 1000mV */ + SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions, + &pulseWidth, 0, 0, 0, 0, 0); + + StreamDataHandler(unit, 100000, ANALOGUE); +} + +/**************************************************************************** +* OpenDevice +* Parameters +* - unit pointer to the UNIT structure, where the handle will be stored +* - serial pointer to the char array containing serial number +* +* Returns +* - PICO_STATUS to indicate success, or if an error occurred +***************************************************************************/ +PICO_STATUS OpenDevice(UNIT *unit, char *serial) +{ + PICO_STATUS status; + + if (serial == NULL) + status = ps2000aOpenUnit(&unit->handle, NULL); + else + status = ps2000aOpenUnit(&unit->handle, serial); + + unit->openStatus = status; + unit->complete = 1; + + return status; +} + +/**************************************************************************** +* HandleDevice +* Parameters +* - unit pointer to the UNIT structure, where the handle will be stored +* +* Returns +* - PICO_STATUS to indicate success, or if an error occurred +***************************************************************************/ +PICO_STATUS HandleDevice(UNIT * unit) +{ + int16_t value = 0; + int32_t i; + struct tPwq pulseWidth; + struct tTriggerDirections directions; + + printf("Handle: %d\n", unit->handle); + if (unit->openStatus != PICO_OK) + { + printf("Unable to open device\n"); + printf("Error code : 0x%08x\n", (uint32_t)unit->openStatus); + while(!_kbhit()); + exit(99); // exit program + } + + printf("Device opened successfully, cycle %d\n\n", ++cycles); + // setup device info - unless it's set already + if (unit->model == MODEL_NONE) + set_info(unit); + timebase = 1; + + PICO_STATUS status = ps2000aMaximumValue(unit->handle, &value); + unit->maxValue = value; + + for (i = 0; i < unit->channelCount; i++) + { + unit->channelSettings[i].enabled = TRUE; + unit->channelSettings[i].DCcoupled = TRUE; + unit->channelSettings[i].range = PS2000A_5V; + } + + memset(&directions, 0, sizeof(struct tTriggerDirections)); + memset(&pulseWidth, 0, sizeof(struct tPwq)); + + SetDefaults(unit); + + /* Trigger disabled */ + SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0); + + return status; +} + +/**************************************************************************** + * DisplaySettings + * Displays information about the user configurable settings in this example + * Parameters + * - unit pointer to the UNIT structure + * + * Returns none + ***************************************************************************/ +void DisplaySettings(UNIT *unit) +{ + int32_t ch; + int32_t voltage; + + printf("\n\nReadings will be scaled in (%s)\n", + (scaleVoltages) ? ("mV") : ("ADC counts")); + + for (ch = 0; ch < unit->channelCount; ch++) + { + if (!(unit->channelSettings[ch].enabled)) + printf("Channel %c Voltage Range = Off\n", 'A' + ch); + else + { + voltage = inputRanges[unit->channelSettings[ch].range]; + printf("Channel %c Voltage Range = ", 'A' + ch); + + if (voltage < 1000) + printf("%dmV\n", voltage); + else + printf("%dV\n", voltage / 1000); + } + } + printf("\n"); +} + +/**************************************************************************** + * ANDAnalogueDigital + * This function shows how to collect a block of data from the analogue + * ports and the digital ports at the same time, triggering when the + * digital conditions AND the analogue conditions are met + * + * Returns none + ***************************************************************************/ +void ANDAnalogueDigitalTriggered(UNIT * unit) +{ + int16_t triggerVoltage = mv_to_adc(1000, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit); + + PS2000A_TRIGGER_CHANNEL_PROPERTIES sourceDetails = + { triggerVoltage, // thresholdUpper + 256 * 10, // thresholdUpper Hysteresis + triggerVoltage, // thresholdLower + 256 * 10, // thresholdLower Hysteresis + PS2000A_CHANNEL_A, // channel + PS2000A_LEVEL }; // mode + + PS2000A_TRIGGER_CONDITIONS conditions = + { PS2000A_CONDITION_TRUE, // Channel A + PS2000A_CONDITION_DONT_CARE, // Channel B + PS2000A_CONDITION_DONT_CARE, // Channel C + PS2000A_CONDITION_DONT_CARE, // Channel D + PS2000A_CONDITION_DONT_CARE, // external + PS2000A_CONDITION_DONT_CARE, // aux + PS2000A_CONDITION_DONT_CARE, // pwq + PS2000A_CONDITION_TRUE }; // digital + + + TRIGGER_DIRECTIONS directions = + { PS2000A_ABOVE, // Channel A + PS2000A_NONE, // Channel B + PS2000A_NONE, // Channel C + PS2000A_NONE, // Channel D + PS2000A_NONE, // external + PS2000A_NONE }; // aux + + PS2000A_DIGITAL_CHANNEL_DIRECTIONS digDirections[2]; // Array size can be up to 16, an entry for each digital bit + + PWQ pulseWidth; + memset(&pulseWidth, 0, sizeof(PWQ)); + + // Set the Digital trigger so it will trigger when bit 0 is Rising and bit 4 is HIGH + // All non-declared bits are taken as PS2000A_DIGITAL_DONT_CARE + // + + digDirections[0].channel = PS2000A_DIGITAL_CHANNEL_0; + digDirections[0].direction = PS2000A_DIGITAL_DIRECTION_RISING; + + digDirections[1].channel = PS2000A_DIGITAL_CHANNEL_4; + digDirections[1].direction = PS2000A_DIGITAL_DIRECTION_HIGH; + + printf("\nCombination Block Triggered\n"); + printf("Collects when value is above %d", + scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value + : sourceDetails.thresholdUpper); // else print ADC Count + printf(scaleVoltages ? "mV\n" : "ADC Counts\n"); + + printf("AND \n"); + printf("Digital Channel 0 --- Rising\n"); + printf("Digital Channel 4 --- High\n"); + printf("Other Digital Channels - Don't Care\n"); + + printf("Press a key to start...\n"); + _getch(); + + SetDefaults(unit); // Enable Analogue channels. + + /* Trigger enabled + * Rising edge + * Threshold = 100mV */ + + if (SetTrigger(unit, &sourceDetails, 1, &conditions, 1, &directions, + &pulseWidth, 0, 0, 0, digDirections, 2) == PICO_OK) + { + BlockDataHandler(unit, "First 10 readings\n", 0, MIXED); + } + + DisableAnalogue(unit); // Disable Analogue ports when finished; +} + +/**************************************************************************** + * ORAnalogueDigital + * This function shows how to collect a block of data from the analogue + * ports and the digital ports at the same time, triggering when either the + * digital conditions OR the analogue conditions are met + * + * Returns none + ***************************************************************************/ +void ORAnalogueDigitalTriggered(UNIT * unit) +{ + int16_t triggerVoltage = mv_to_adc(1000, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit); + + PS2000A_TRIGGER_CHANNEL_PROPERTIES sourceDetails = + { triggerVoltage, // thresholdUpper + 256 * 10, // thresholdUpper Hysteresis + triggerVoltage, // thresholdLower + 256 * 10, // thresholdLower Hysteresis + PS2000A_CHANNEL_A, // channel + PS2000A_LEVEL }; // mode + + + PS2000A_TRIGGER_CONDITIONS conditions[2]; + + TRIGGER_DIRECTIONS directions = + { PS2000A_RISING, // Channel A + PS2000A_NONE, // Channel B + PS2000A_NONE, // Channel C + PS2000A_NONE, // Channel D + PS2000A_NONE, // external + PS2000A_NONE }; // aux + + PS2000A_DIGITAL_CHANNEL_DIRECTIONS digDirections[2]; // Array size can be up to 16, an entry for each digital bit + + PWQ pulseWidth; + + conditions[0].channelA = PS2000A_CONDITION_TRUE; // Channel A + conditions[0].channelB = PS2000A_CONDITION_DONT_CARE; // Channel B + conditions[0].channelC = PS2000A_CONDITION_DONT_CARE; // Channel C + conditions[0].channelD = PS2000A_CONDITION_DONT_CARE; // Channel D + conditions[0].external = PS2000A_CONDITION_DONT_CARE; // external + conditions[0].aux = PS2000A_CONDITION_DONT_CARE; // aux + conditions[0].pulseWidthQualifier = PS2000A_CONDITION_DONT_CARE; // pwq + conditions[0].digital = PS2000A_CONDITION_DONT_CARE; // digital + + + conditions[1].channelA = PS2000A_CONDITION_DONT_CARE; // Channel A + conditions[1].channelB = PS2000A_CONDITION_DONT_CARE; // Channel B + conditions[1].channelC = PS2000A_CONDITION_DONT_CARE; // Channel C + conditions[1].channelD = PS2000A_CONDITION_DONT_CARE; // Channel D + conditions[1].external = PS2000A_CONDITION_DONT_CARE; // external + conditions[1].aux = PS2000A_CONDITION_DONT_CARE; // aux + conditions[1].pulseWidthQualifier = PS2000A_CONDITION_DONT_CARE; // pwq + conditions[1].digital = PS2000A_CONDITION_TRUE; // digital + + + memset(&pulseWidth, 0, sizeof(PWQ)); + + // Set the Digital trigger so it will trigger when bit 0 is Rising and bit 4 is HIGH + // All non-declared bits are taken as PS2000A_DIGITAL_DONT_CARE + // + + digDirections[0].channel = PS2000A_DIGITAL_CHANNEL_0; + digDirections[0].direction = PS2000A_DIGITAL_DIRECTION_RISING; + + digDirections[1].channel = PS2000A_DIGITAL_CHANNEL_4; + digDirections[1].direction = PS2000A_DIGITAL_DIRECTION_HIGH; + + printf("\nCombination Block Triggered\n"); + printf("Collects when value rises past %d", + scaleVoltages ? adc_to_mv(sourceDetails.thresholdUpper, + unit->channelSettings[PS2000A_CHANNEL_A].range, unit) // If scaleVoltages, print mV value + : sourceDetails.thresholdUpper); // else print ADC Count + printf(scaleVoltages ? "mV\n" : "ADC Counts\n"); + + printf("OR \n"); + printf("Digital Channel 0 --- Rising\n"); + printf("Digital Channel 4 --- High\n"); + printf("Other Digital Channels - Don't Care\n"); + + printf("Press a key to start...\n"); + _getch(); + + SetDefaults(unit); // enable analogue ports + + /* Trigger enabled + * Rising edge + * Threshold = 1000mV */ + + if (SetTrigger(unit, &sourceDetails, 1, conditions, 2, &directions, + &pulseWidth, 0, 0, 0, digDirections, 2) == PICO_OK) + { + + BlockDataHandler(unit, "First 10 readings\n", 0, MIXED); + } + + DisableAnalogue(unit); // Disable Analogue ports when finished; +} + +/**************************************************************************** + * DigitalBlockTriggered + * This function shows how to collect a block of data from the digital ports + * with triggering enabled + * + * Returns none + ***************************************************************************/ + +void DigitalBlockTriggered(UNIT * unit) +{ + PWQ pulseWidth; + TRIGGER_DIRECTIONS directions; + PS2000A_DIGITAL_CHANNEL_DIRECTIONS digDirections[2]; // Array size can be up to 16, an entry for each digital bit + + PS2000A_TRIGGER_CONDITIONS conditions = + { PS2000A_CONDITION_DONT_CARE, // Channel A + PS2000A_CONDITION_DONT_CARE, // Channel B + PS2000A_CONDITION_DONT_CARE, // Channel C + PS2000A_CONDITION_DONT_CARE, // Channel D + PS2000A_CONDITION_DONT_CARE, // external + PS2000A_CONDITION_DONT_CARE, // aux + PS2000A_CONDITION_DONT_CARE, // pwq + PS2000A_CONDITION_TRUE }; // digital + + + printf("\nDigital Block Triggered\n"); + + memset(&directions, 0, sizeof(TRIGGER_DIRECTIONS)); + memset(&pulseWidth, 0, sizeof(PWQ)); + + printf("Collect block of data when the trigger occurs...\n"); + printf("Digital Channel 0 --- Rising\n"); + printf("Digital Channel 4 --- High\n"); + printf("Other Digital Channels - Don't Care\n"); + + digDirections[0].channel = PS2000A_DIGITAL_CHANNEL_0; + digDirections[0].direction = PS2000A_DIGITAL_DIRECTION_RISING; + + digDirections[1].channel = PS2000A_DIGITAL_CHANNEL_4; + digDirections[1].direction = PS2000A_DIGITAL_DIRECTION_HIGH; + + if (SetTrigger(unit, NULL, 0, &conditions, 1, &directions, &pulseWidth, 0, + 0, 0, digDirections, 2) == PICO_OK) + { + printf("Press a key to start...\n"); + _getch(); + BlockDataHandler(unit, "First 10 readings\n", 0, DIGITAL); + } +} + +/**************************************************************************** + * DigitalBlockImmediate + * This function shows how to collect a block of data from the digital ports + * with triggering disabled + * + * Returns none + ***************************************************************************/ +void DigitalBlockImmediate(UNIT *unit) +{ + PWQ pulseWidth; + TRIGGER_DIRECTIONS directions; + PS2000A_DIGITAL_CHANNEL_DIRECTIONS digDirections; + + printf("\nDigital Block Immediate\n"); + memset(&directions, 0, sizeof(TRIGGER_DIRECTIONS)); + memset(&pulseWidth, 0, sizeof(PWQ)); + memset(&digDirections, 0, sizeof(PS2000A_DIGITAL_CHANNEL_DIRECTIONS)); + + SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, + &digDirections, 0); + + printf("Press a key to start...\n"); + _getch(); + + BlockDataHandler(unit, "First 10 readings\n", 0, DIGITAL); +} + +/**************************************************************************** + * DigitalStreamingAggregated + * this function demonstrates how to collect a stream of Aggregated data + * from the unit's Digital inputs (start collecting immediately) + ***************************************************************************/ +void DigitalStreamingAggregated(UNIT * unit) +{ + struct tPwq pulseWidth; + struct tTriggerDirections directions; + + memset(&pulseWidth, 0, sizeof(struct tPwq)); + memset(&directions, 0, sizeof(struct tTriggerDirections)); + + printf("Digital streaming with Aggregation...\n"); + printf("Press a key to start...\n"); + _getch(); + + /* Trigger disabled */ + SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0); + + StreamDataHandler(unit, 0, AGGREGATED); +} + +/**************************************************************************** + * DigitalStreamingImmediate + * this function demonstrates how to collect a stream of data + * from the unit's Digital inputs (start collecting immediately) + ***************************************************************************/ +void DigitalStreamingImmediate(UNIT * unit) +{ + struct tPwq pulseWidth; + struct tTriggerDirections directions; + + memset(&pulseWidth, 0, sizeof(struct tPwq)); + memset(&directions, 0, sizeof(struct tTriggerDirections)); + + printf("Digital streaming...\n"); + printf("Press a key to start...\n"); + _getch(); + + /* Trigger disabled */ + SetTrigger(unit, NULL, 0, NULL, 0, &directions, &pulseWidth, 0, 0, 0, 0, 0); + + StreamDataHandler(unit, 0, DIGITAL); +} + +/**************************************************************************** + * DigitalMenu + * Displays digital examples available + * Parameters + * - unit pointer to the UNIT structure + * + * Returns none + ***************************************************************************/ +void DigitalMenu(UNIT *unit) +{ + char ch; + int16_t enabled = TRUE; + int16_t disabled = !enabled; + + DisableAnalogue(unit); // Disable Analogue ports; + SetDigitals(unit, enabled); // Enable Digital ports + + ch = ' '; + while (ch != 'X') + { + printf("\n"); + printf("\nDigital Port Menu\n\n"); + printf("B - Digital Block Immediate\n"); + printf("T - Digital Block Triggered\n"); + printf("A - Analogue 'AND' Digital Triggered Block\n"); + printf("O - Analogue 'OR' Digital Triggered Block\n"); + printf("S - Digital Streaming Mode\n"); + printf("V - Digital Streaming Aggregated\n"); + printf("X - Return to previous menu\n\n"); + printf("Operation:"); + + ch = toupper(_getch()); + + printf("\n\n"); + switch (ch) + { + case 'B': + DigitalBlockImmediate(unit); + break; + + case 'T': + DigitalBlockTriggered(unit); + break; + + case 'A': + ANDAnalogueDigitalTriggered(unit); + break; + + case 'O': + ORAnalogueDigitalTriggered(unit); + break; + + case 'S': + DigitalStreamingImmediate(unit); + break; + + case 'V': + DigitalStreamingAggregated(unit); + break; + } + } + + SetDigitals(unit, disabled); // Disable Digital ports when finished +} + +/**************************************************************************** +* MainMenu +* Controls default functions of the seelected unit +* Parameters +* - unit pointer to the UNIT structure +* +* Returns none +***************************************************************************/ +void MainMenu(UNIT *unit) +{ + char ch = '.'; + while (ch != 'X') + { + DisplaySettings(unit); + + printf("\n"); + printf( + "B - Immediate block V - Set voltages\n"); + printf( + "T - Triggered block I - Set timebase\n"); + printf( + "E - Collect a block of data using ETS A - ADC counts/mV\n"); + printf( + "R - Collect set of rapid captures G - Signal generator\n"); + printf("S - Immediate streaming\n"); + printf("W - Triggered streaming\n"); + printf(unit->digitalPorts ? "D - Digital Ports menu\n" : ""); + printf(" X - Exit\n\n"); + printf("Operation:"); + + ch = toupper(_getch()); + + printf("\n\n"); + switch (ch) + { + case 'B': + CollectBlockImmediate(unit); + break; + + case 'T': + CollectBlockTriggered(unit); + break; + + case 'R': + CollectRapidBlock(unit); + break; + + case 'S': + CollectStreamingImmediate(unit); + break; + + case 'W': + CollectStreamingTriggered(unit); + break; + + case 'E': + if(unit->ETS == FALSE) + { + printf("This model does not support ETS\n\n"); + break; + } + + CollectBlockEts(unit); + break; + + case 'G': + if(unit->signalGenerator == FALSE) + { + printf("This model does not have a signal generator\n\n"); + break; + } + + SetSignalGenerator(unit); + break; + + case 'V': + SetVoltages(unit); + break; + + case 'I': + SetTimebase(unit); + break; + + case 'A': + scaleVoltages = !scaleVoltages; + break; + + case 'D': + if (unit->digitalPorts) + DigitalMenu(unit); + break; + + case 'X': + break; + + default: + printf("Invalid operation\n"); + break; + } + } +} + + +/**************************************************************************** +* main +* +***************************************************************************/ +int main(void) +{ +#define MAX_PICO_DEVICES 64 +#define TIMED_LOOP_STEP 500 + char ch; + uint16_t devCount = 0, listIter = 0, openIter = 0; + //device indexer - 64 chars - 64 is maximum number of picoscope devices handled by driver + char devChars[] = + "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#"; + PICO_STATUS status = PICO_OK; + UNIT allUnits[MAX_PICO_DEVICES]; + + printf("PS2000A driver example program\n"); + printf("\nEnumerating Units...\n"); + + do + { + memset(&(allUnits[devCount]),0,sizeof (UNIT)); + status = OpenDevice(&(allUnits[devCount]),NULL); + if(status == PICO_OK || status == PICO_POWER_SUPPLY_NOT_CONNECTED || status == PICO_USB3_0_DEVICE_NON_USB3_0_PORT) + { + allUnits[devCount++].openStatus = status; + } + } while(status != PICO_NOT_FOUND); + + if (devCount == 0) + { + printf("Picoscope devices not found\n"); + return 1; + } + // if there is only one device, open and handle it here + if (devCount == 1) + { + printf("Found one device, opening...\n\n"); + status = allUnits[0].openStatus; + if (status == PICO_OK || status == PICO_POWER_SUPPLY_NOT_CONNECTED + || status == PICO_USB3_0_DEVICE_NON_USB3_0_PORT) + status = HandleDevice(&allUnits[0]); + if (status != PICO_OK) + { + printf("Picoscope devices open failed, error code 0x%x\n",(uint32_t)status); + return 1; + } + printf("Model\t: %7s\nS/N\t: %s\n", allUnits[0].modelString, allUnits[0].serial); + MainMenu(&allUnits[0]); + CloseDevice(&allUnits[0]); + printf("Exit...\n"); + return 0; + } + else + { + // more than one unit + printf("Found %d devices, initializing...\n\n", devCount); + for (listIter = 0; listIter < devCount; listIter++) + { + if ((allUnits[listIter].openStatus == PICO_OK + || allUnits[listIter].openStatus + == PICO_POWER_SUPPLY_NOT_CONNECTED + || allUnits[listIter].openStatus + == PICO_USB3_0_DEVICE_NON_USB3_0_PORT)) + { + set_info(&allUnits[listIter]); + openIter++; + } + } + } + // None + if (openIter == 0) + { + printf("Picoscope devices init failed\n"); + return 1; + } + // Just one - handle it here + if (openIter == 1) + { + for (listIter = 0; listIter < devCount; listIter++) + { + if (!(allUnits[listIter].openStatus == PICO_OK + || allUnits[listIter].openStatus + == PICO_POWER_SUPPLY_NOT_CONNECTED + || allUnits[listIter].openStatus + == PICO_USB3_0_DEVICE_NON_USB3_0_PORT)) + break; + } + printf("One device openned successfuly\n"); + printf("Model\t: %s\nS/N\t: %s\n", allUnits[listIter].modelString, allUnits[listIter].serial); + status = HandleDevice(&allUnits[listIter]); + if (status != PICO_OK) + { + printf("Picoscope device open failed, error code 0x%x\n", (uint32_t)status); + return 1; + } + MainMenu(&allUnits[listIter]); + CloseDevice(&allUnits[listIter]); + printf("Exit...\n"); + return 0; + } + printf("Found %d devices, pick one to open from the list:\n", devCount); + for (listIter = 0; listIter < devCount; listIter++) + { + printf("%c) Picoscope %7s S/N: %s\n", devChars[listIter], + allUnits[listIter].modelString, allUnits[listIter].serial); + } + printf("ESC) Cancel\n"); + + ch = '.'; + //if escape + while (ch != 27) + { + ch = _getch(); + //if escape + if (ch == 27) + continue; + for (listIter = 0; listIter < devCount; listIter++) + { + if (ch == devChars[listIter]) + { + printf("Option %c) selected, opening Picoscope %7s S/N: %s\n", + devChars[listIter], allUnits[listIter].modelString, + allUnits[listIter].serial); + if ((allUnits[listIter].openStatus == PICO_OK + || allUnits[listIter].openStatus + == PICO_POWER_SUPPLY_NOT_CONNECTED + || allUnits[listIter].openStatus + == PICO_USB3_0_DEVICE_NON_USB3_0_PORT)) + status = HandleDevice(&allUnits[listIter]); + if (status != PICO_OK) + { + printf("Picoscope devices open failed, error code 0x%x\n", (uint32_t)status); + return 1; + } + MainMenu(&allUnits[listIter]); + + printf("Found %d devices, pick one to open from the list:\n",devCount); + for (listIter = 0; listIter < devCount; listIter++) + { + printf("%c) Picoscope %7s S/N: %s\n", devChars[listIter], + allUnits[listIter].modelString, + allUnits[listIter].serial); + } + printf("ESC) Cancel\n"); + } + } + } + for (listIter = 0; listIter < devCount; listIter++) + { + CloseDevice(&allUnits[listIter]); + } + printf("Exit...\n"); + return 0; +} diff --git a/utils/picoscope/picocontrol b/utils/picoscope/picocontrol new file mode 100755 index 0000000000000000000000000000000000000000..c152a75ef23062b62284e24e95fed8de4d9253a5 GIT binary patch literal 15011 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 NiJi&jI+xV)e*sumJM{nn literal 0 HcmV?d00001 diff --git a/utils/picoscope/picocontrol.c b/utils/picoscope/picocontrol.c new file mode 100644 index 0000000..182d192 --- /dev/null +++ b/utils/picoscope/picocontrol.c @@ -0,0 +1,127 @@ +/** + This is a little CLI program to control the picoscope frequency + generator coming with the Pico Labs Picoscope 2206a oscilloscope + + Mark Koennecke, May 2015 + + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef PICO_STATUS +#include +#endif + + +static short handle; + +/*--------------------------------------------------------------*/ +static void StopPico(void) +{ + ps2000aCloseUnit(handle); +} +/*--------------------------------------------------------------*/ +static void SetGenerator(long freq, float ampl) +{ + int status; + + if(freq == 0){ + status = ps2000aSetSigGenBuiltIn(handle, + 0, + 0, + PS2000A_DC_VOLTAGE, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0); + } else { + status = ps2000aSetSigGenBuiltIn(handle, + 0, + (unsigned long)ampl, + PS2000A_SINE, + (float)freq, + (float)freq, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0); + } + if(status != PICO_OK){ + printf("Failed to configure signal generator with %d\n", status); + } +} +/*----------------------------------------------------------------------*/ +int main(int argc, char *argv[]) +{ + int status; + long int freq = 1000; + float mult = 1000000, ampl = 1.*mult, tmp; + char line[80], token[80]; + + status = ps2000aOpenUnit(&handle, NULL); + if(status != PICO_OK){ + printf("Failed to open picoscope with %d\n", status); + exit(1); + } + + atexit(StopPico); + + while(1) { + memset(line,0,sizeof(line)); + fgets(line,sizeof(line),stdin); + + if(strstr(line,"freq") != NULL){ + status = sscanf(line,"%s %f",token, &tmp); + if(status == 2){ + freq = (unsigned int) tmp; + SetGenerator(freq,ampl); + printf("OK\n"); + } else { + printf("freq %ld\n", freq); + } + } else if(strstr(line,"ampl") != NULL){ + status = sscanf(line,"%s %f",token, &tmp); + if(status == 2){ + ampl = tmp*mult; + SetGenerator(freq,ampl); + printf("OK\n"); + } else { + printf("ampl %f\n", ampl/mult); + } + } else if(strstr(line,"on") != NULL){ + SetGenerator(freq,ampl); + printf("OK\n"); + }else if(strstr(line,"off") != NULL){ + SetGenerator(0,0); + printf("OK\n"); + }else if(strstr(line,"exit") != NULL){ + ps2000aCloseUnit(handle); + break; + } else { + printf("Parameter commands: freq (hz), ampl( V), on, off\n"); + } + fflush(stdout); + } + + +} diff --git a/utils/picoscope/picocontrol.plist b/utils/picoscope/picocontrol.plist new file mode 100644 index 0000000..5769d11 --- /dev/null +++ b/utils/picoscope/picocontrol.plist @@ -0,0 +1,41 @@ + + + + + Disabled + + Label + picocontrol + Program + /Users/sinquser/src/picoscope/picocontrol + EnvironmentVariables + + DYLD_LIBRARY_PATH + /Applications/PicoScope6.app/Contents/Resources/lib + + Sockets + + Listeners + + SockServiceName + ssh + Bonjour + + ssh + sftp-ssh + + + + inetdCompatibility + + Wait + + + StandardErrorPath + /dev/null + SHAuthorizationRight + system.preferences + POSIXSpawnType + Interactive + + diff --git a/utils/picoscope/picocontrol.xinetd b/utils/picoscope/picocontrol.xinetd new file mode 100755 index 0000000..9a2b794 --- /dev/null +++ b/utils/picoscope/picocontrol.xinetd @@ -0,0 +1,12 @@ +service picocontrol +{ + socket_type = stream + protocol = tcp + port = 3030 + type = UNLISTED + wait = no + user = root + server = /usr/bin/picocontrol +} + + diff --git a/utils/picoscope/picosig b/utils/picoscope/picosig new file mode 100755 index 0000000000000000000000000000000000000000..02a48db8bb9eabc78899b2ba4af9893b479224d3 GIT binary patch literal 7585 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef PICO_STATUS +#include +#endif + + +int main(int argc, char *argv[]) +{ + int freq, ampl, status; + short handle; + + if(argc < 3) { + printf("Usage:\n\tpicosig freq ampl\n"); + exit(1); + } + + freq = atoi(argv[1]); + ampl = atoi(argv[2]); + + printf("Found freq, ample = %d %d\n", freq, ampl); + + status = ps2000aOpenUnit(&handle, NULL); + if(status != PICO_OK){ + printf("Failed to open picoscope with %d\n", status); + exit(1); + } + + status = ps2000aSetSigGenBuiltIn(handle, + 0, + (unsigned long)ampl, + PS2000A_SINE, + (float)freq, + (float)freq, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0); + if(status != PICO_OK){ + printf("Failed to configure signal generator with %d\n", status); + exit(1); + } + + sleep(5); + + ps2000aCloseUnit(handle); + printf("Done\n"); +}