From 2fb070563cc61d6f7d3497e2c08795517c5e92fe Mon Sep 17 00:00:00 2001 From: WillForan Date: Wed, 22 Feb 2023 13:18:27 -0500 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20http=5Fttl.py:=20add=20extra=20?= =?UTF-8?q?wait=20for=20start=20and=20stop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http_ttl.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/http_ttl.py b/http_ttl.py index ed38fc2..f610f22 100755 --- a/http_ttl.py +++ b/http_ttl.py @@ -61,9 +61,9 @@ def print_timestamp(self, ttl): print(f"{ttl} {diff.total_seconds():.03f}") return True - def wait_and_zero(self): + def wait_and_zero(self, wait=.002): # TODO: more percise sleeping psychopy.core.wait(.005) or psychtoolbox.WaitSecs(.005) - time.sleep(.002) # wait 2ms and send zero. not precise enough? + time.sleep(wait) # wait 2ms and send zero. not precise enough? self.send(0, False) # if we're lucky setData zero's pins that aren't used # self.port.setData(0) @@ -120,8 +120,12 @@ def send(self, ttl, zero=True): actual_ttl = 250 # always high self.dev.DOut(self.dev.DIO_PORTA, actual_ttl) # always zero. we'll only ever send hi + wait=.002 + # to ID start and end, wait twice as long + if ttl in [128,129]: + wait=.005 if zero: - self.wait_and_zero() + self.wait_and_zero(wait=wait) # ## BUTTON BOXES ## From ed78112257d3e816bbd3d5ecd953f66a8924fbe1 Mon Sep 17 00:00:00 2001 From: WillForan Date: Wed, 25 Oct 2023 12:02:09 -0400 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=9A=B8=20http=5Fttl.py:=20test=20now?= =?UTF-8?q?=20test=5Fhttp,=20more=20notes=20to=20user=20for=20test=20cases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http_ttl.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/http_ttl.py b/http_ttl.py index a915879..36565d2 100755 --- a/http_ttl.py +++ b/http_ttl.py @@ -336,12 +336,14 @@ async def seeg(verbose=False): http_run(logger) await asyncio.create_task(rb.watch()) + async def test_DAQ(verbose=False): + "only test DAQ. loop forever: send high and auto reset" hw = DAQ(verbose=verbose) while True: await asyncio.sleep(1) - print(f"sending high and zeroing") - hw.send(250) # 250 just has to be non-zero + print("sending high and zeroing") + hw.send(250) # 250 just has to be non-zero async def rtbox_test(verbose=False): @@ -349,10 +351,12 @@ async def rtbox_test(verbose=False): hw = Hardware(verbose=verbose) kb = KB() rb = RTBox(hw, kb, verbose) + print("push button box keys. should see events here") await asyncio.create_task(rb.watch()) async def fakeeeg(usekeyboard=False, verbose=False): + "listen on port, but don't interface with DAQ or RTBox" hw = Hardware(verbose=verbose) kb = KB() http_run(hw) @@ -360,6 +364,9 @@ async def fakeeeg(usekeyboard=False, verbose=False): # kludge. disable trigger function so we dont send the 'a' key every 5 seconds if not usekeyboard: rb.trigger = lambda a: 1 + + print("listening for ttl on http. no RTBox or DAQ") + print("in new term try sending code: curl http://127.0.0.1:8888/1") # need this await or we'll exit as soon as we send the first trigger await asyncio.create_task(rb.watch()) @@ -367,8 +374,8 @@ async def fakeeeg(usekeyboard=False, verbose=False): def parser(args): import argparse p = argparse.ArgumentParser(description="Intercept http queries and watch ButtonBox/PhotoDiode") - p.add_argument('place', choices=["loeff", "seeg", "test", "test_rtbox", "test_DAQ"], help='where (also how) to use button and ttl') - p.add_argument('-k','--keyboard', help='use keyboard (only for "test")', action='store_true', dest="usekeyboard") + p.add_argument('place', choices=["loeff", "seeg", "test_http", "test_rtbox", "test_DAQ"], help='where (also how) to use button and ttl') + p.add_argument('-k','--keyboard', help='use keyboard (only for "test_http")', action='store_true', dest="usekeyboard") p.add_argument('-v','--verbose', help='additonal printing', action='store_true', dest="verbose") return p.parse_args(args) @@ -380,7 +387,7 @@ def parser(args): asyncio.run(loeffeeg(verbose=args.verbose)) elif args.place == "seeg": asyncio.run(seeg(verbose=args.verbose)) - elif args.place == "test": + elif args.place == "test_http": asyncio.run(fakeeeg(args.usekeyboard, verbose=args.verbose)) elif args.place == "test_DAQ": asyncio.run(test_DAQ(verbose=args.verbose)) From 7908c33ddbf421cbcb2e79e57e6c466f56a875a8 Mon Sep 17 00:00:00 2001 From: Will Foran Date: Wed, 29 Nov 2023 12:35:12 -0500 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=9A=B8=20http=5Fttl.py:=20add=20cedru?= =?UTF-8?q?s=20and=20lpt=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http_ttl.py | 34 ++++++++++++++++++++++++++++++---- loeffeeg_test.bat | 7 +++++++ 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 loeffeeg_test.bat diff --git a/http_ttl.py b/http_ttl.py index 36565d2..1238421 100755 --- a/http_ttl.py +++ b/http_ttl.py @@ -338,7 +338,7 @@ async def seeg(verbose=False): async def test_DAQ(verbose=False): - "only test DAQ. loop forever: send high and auto reset" + "only test DAQ. loop forever: send high and auto reset (seeg)" hw = DAQ(verbose=verbose) while True: await asyncio.sleep(1) @@ -346,8 +346,17 @@ async def test_DAQ(verbose=False): hw.send(250) # 250 just has to be non-zero +async def test_LPT(verbose=False, address=0xD010): + "only test LPT. loop forever: send high and auto reset (loef eeg)" + hw = LPT(address=address, verbose=verbose) + while True: + await asyncio.sleep(1) + print("sending high and zeroing") + hw.send(250) + + async def rtbox_test(verbose=False): - "no http server, no DAQ. just RTBox with generic hardware class" + "no http server, no DAQ. just RTBox with generic hardware class (seeg)" hw = Hardware(verbose=verbose) kb = KB() rb = RTBox(hw, kb, verbose) @@ -355,6 +364,15 @@ async def rtbox_test(verbose=False): await asyncio.create_task(rb.watch()) +async def cedrus_test(verbose=False): + "test cedrus response button box (loef eeg)" + hw = Hardware(verbose=verbose) + kb = KB() + rb = Cedrus(hw, kb) + http_run(hw) + await asyncio.create_task(rb.watch()) + + async def fakeeeg(usekeyboard=False, verbose=False): "listen on port, but don't interface with DAQ or RTBox" hw = Hardware(verbose=verbose) @@ -374,7 +392,10 @@ async def fakeeeg(usekeyboard=False, verbose=False): def parser(args): import argparse p = argparse.ArgumentParser(description="Intercept http queries and watch ButtonBox/PhotoDiode") - p.add_argument('place', choices=["loeff", "seeg", "test_http", "test_rtbox", "test_DAQ"], help='where (also how) to use button and ttl') + p.add_argument('place', choices=["loeff", "seeg", "test_http", + "test_rtbox", "test_DAQ", + "test_cedrus", "test_lpt"], + help='where (also how) to use button and ttl') p.add_argument('-k','--keyboard', help='use keyboard (only for "test_http")', action='store_true', dest="usekeyboard") p.add_argument('-v','--verbose', help='additonal printing', action='store_true', dest="verbose") return p.parse_args(args) @@ -389,10 +410,15 @@ def parser(args): asyncio.run(seeg(verbose=args.verbose)) elif args.place == "test_http": asyncio.run(fakeeeg(args.usekeyboard, verbose=args.verbose)) + elif args.place == "test_DAQ": asyncio.run(test_DAQ(verbose=args.verbose)) - elif args.place == "test_rtbox": asyncio.run(rtbox_test(verbose=args.verbose)) + + elif args.place == "test_cedrus": + asyncio.run(cedrus_test(verbose=args.verbose)) + elif args.place == "test_lpt": + asyncio.run(test_LPT(verbose=args.verbose)) else: print(f"unkown place '{args.place}'! -- argparse should have caught this") diff --git a/loeffeeg_test.bat b/loeffeeg_test.bat new file mode 100644 index 0000000..6709a0b --- /dev/null +++ b/loeffeeg_test.bat @@ -0,0 +1,7 @@ +Rem test python bridge for ltp and cedrus box hardware +set PYTHON=C:\Program Files\PsychoPy\python.exe +echo ctrl-c to stop each test +echo TESTING CEDRUS BOX +"%PYTHON%" http_ttl.py test_cedrus +echo TESTING LPT +"%PYTHON%" http_ttl.py test_lpt