NXT 0.2.2 → 0.2.3
raw patch · 2 files changed
+251/−251 lines, 2 filesdep ~NXTPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: NXT
API changes (from Hackage documentation)
Files
- NXT.cabal +114/−114
- remote/remote.nxc +137/−137
NXT.cabal view
@@ -1,114 +1,114 @@-Name: NXT -Version: 0.2.2 -Synopsis: A Haskell interface to Lego Mindstorms NXT -Description: A Haskell interface to Lego Mindstorms NXT over Bluetoooth. It supports direct commands, messages and - many sensors (also unofficial). It has also support for a simple message-based control of a NXT brick - via remotely executed program (basic NXC code included). - . - It contains three simple programs: @nxt-upload@ for uploading files to a NXT brick, @nxt-status@ for displaying - a NXT brick status, and @nxt-shutdown@ for remote shutdown of a NXT brick. - . - It works on Linux, Mac OS X and Windows. - . - Feel free to contribute additional features, interfaces for more sensors and propose or write other - (example) programs. -License: LGPL-3 -License-file: LICENSE -Author: Mitar Milutinovic -Maintainer: mitar.haskell@tnode.com -Copyright: (c) 2011-2012 Mitar Milutinovic -Category: Robotics -Build-type: Simple -Cabal-version: >= 1.10 -Stability: provisional -Homepage: http://mitar.tnode.com -Extra-source-files: remote/remote.rxe, - remote/remote.nxc, - ffi/blue.h, - tests/Main.hs, - tests/Robotics/NXT/Basic.hs - -Library - Exposed-modules: Robotics.NXT, - Robotics.NXT.MotorControl, - Robotics.NXT.Remote, - Robotics.NXT.Sensor.Compass, - Robotics.NXT.Sensor.Ultrasonic - Build-depends: base >= 4.3 && < 5, - mtl >= 1.1 && < 3, - bytestring >= 0.9 && < 1, - time >= 1.1 && < 2, - serialport >= 0.4.3 && < 1 - Other-modules: Robotics.NXT.Data, - Robotics.NXT.Errors, - Robotics.NXT.Protocol, - Robotics.NXT.Types, - Robotics.NXT.Internals, - Robotics.NXT.Externals, - Robotics.NXT.BluetoothUtils - HS-source-dirs: lib - GHC-options: -Wall - GHC-prof-options: -Wall - GHC-shared-options: -Wall - Default-language: Haskell2010 - - if !os(windows) - Build-depends: unix >= 2.4 && < 3 - - if os(linux) - C-sources: ffi/blue.c - Includes: ffi/blue.h - Extra-libraries: bluetooth - -Source-repository head - type: mercurial - location: https://bitbucket.org/mitar/nxt - -Executable nxt-shutdown - Main-is: Shutdown.hs - HS-source-dirs: src - Build-depends: base >= 4.3 && < 5, - mtl >= 1.1 && < 3, - NXT == 0.2.2 - GHC-options: -Wall - Default-language: Haskell2010 - -Executable nxt-status - Main-is: Status.hs - HS-source-dirs: src - Build-depends: base >= 4.3 && < 5, - mtl >= 1.1 && < 3, - NXT == 0.2.2 - GHC-options: -Wall - Default-language: Haskell2010 - -Executable nxt-upload - Main-is: UploadFiles.hs - HS-source-dirs: src - Build-depends: base >= 4.3 && < 5, - mtl >= 1.1 && < 3, - bytestring >= 0.9 && < 1, - filepath >= 1.1 && < 2, - NXT == 0.2.2 - GHC-options: -Wall - Default-language: Haskell2010 - -Test-suite nxt-tests - Type: exitcode-stdio-1.0 - X-uses-tf: true - Build-depends: base >= 4, - HUnit >= 1.2 && < 2, - QuickCheck >= 2.4 && < 3, - test-framework >= 0.4 && < 1, - test-framework-quickcheck2 >= 0.2 && < 1, - test-framework-hunit >= 0.2 && < 1, - mtl >= 1.1 && < 3, - time >= 1.2 && < 2, - bytestring >= 0.9 && < 1.0, - filepath >= 1.2 && < 2, - NXT == 0.2.2 - GHC-options: -Wall -rtsopts - Default-language: Haskell2010 - HS-source-dirs: tests - Main-is: Main.hs - Other-modules: Robotics.NXT.Basic +Name: NXT+Version: 0.2.3+Synopsis: A Haskell interface to Lego Mindstorms NXT+Description: A Haskell interface to Lego Mindstorms NXT over Bluetoooth. It supports direct commands, messages and+ many sensors (also unofficial). It has also support for a simple message-based control of a NXT brick+ via remotely executed program (basic NXC code included).+ .+ It contains three simple programs: @nxt-upload@ for uploading files to a NXT brick, @nxt-status@ for displaying+ a NXT brick status, and @nxt-shutdown@ for remote shutdown of a NXT brick.+ .+ It works on Linux, Mac OS X and Windows.+ .+ Feel free to contribute additional features, interfaces for more sensors and propose or write other+ (example) programs.+License: LGPL-3+License-file: LICENSE+Author: Mitar Milutinovic+Maintainer: mitar.haskell@tnode.com+Copyright: (c) 2011-2013 Mitar Milutinovic+Category: Robotics+Build-type: Simple+Cabal-version: >= 1.10+Stability: provisional+Homepage: http://mitar.tnode.com+Extra-source-files: remote/remote.rxe,+ remote/remote.nxc,+ ffi/blue.h,+ tests/Main.hs,+ tests/Robotics/NXT/Basic.hs++Library+ Exposed-modules: Robotics.NXT,+ Robotics.NXT.MotorControl,+ Robotics.NXT.Remote,+ Robotics.NXT.Sensor.Compass,+ Robotics.NXT.Sensor.Ultrasonic+ Build-depends: base >= 4.3 && < 5,+ mtl >= 1.1 && < 3,+ bytestring >= 0.9 && < 1,+ time >= 1.1 && < 2,+ serialport >= 0.4.3 && < 1+ Other-modules: Robotics.NXT.Data,+ Robotics.NXT.Errors,+ Robotics.NXT.Protocol,+ Robotics.NXT.Types,+ Robotics.NXT.Internals,+ Robotics.NXT.Externals,+ Robotics.NXT.BluetoothUtils+ HS-source-dirs: lib+ GHC-options: -Wall+ GHC-prof-options: -Wall+ GHC-shared-options: -Wall+ Default-language: Haskell2010++ if !os(windows)+ Build-depends: unix >= 2.4 && < 3++ if os(linux)+ C-sources: ffi/blue.c+ Includes: ffi/blue.h+ Extra-libraries: bluetooth++Source-repository head+ type: git+ location: git://github.com/mitar/nxt.git++Executable nxt-shutdown+ Main-is: Shutdown.hs+ HS-source-dirs: src+ Build-depends: base >= 4.3 && < 5,+ mtl >= 1.1 && < 3,+ NXT == 0.2.3+ GHC-options: -Wall+ Default-language: Haskell2010++Executable nxt-status+ Main-is: Status.hs+ HS-source-dirs: src+ Build-depends: base >= 4.3 && < 5,+ mtl >= 1.1 && < 3,+ NXT == 0.2.3+ GHC-options: -Wall+ Default-language: Haskell2010++Executable nxt-upload+ Main-is: UploadFiles.hs+ HS-source-dirs: src+ Build-depends: base >= 4.3 && < 5,+ mtl >= 1.1 && < 3,+ bytestring >= 0.9 && < 1,+ filepath >= 1.1 && < 2,+ NXT == 0.2.3+ GHC-options: -Wall+ Default-language: Haskell2010++Test-suite nxt-tests+ Type: exitcode-stdio-1.0+ X-uses-tf: true+ Build-depends: base >= 4,+ HUnit >= 1.2 && < 2,+ QuickCheck >= 2.4 && < 3,+ test-framework >= 0.4 && < 1,+ test-framework-quickcheck2 >= 0.2 && < 1,+ test-framework-hunit >= 0.2 && < 1,+ mtl >= 1.1 && < 3,+ time >= 1.2 && < 2,+ bytestring >= 0.9 && < 1.0,+ filepath >= 1.2 && < 2,+ NXT == 0.2.3+ GHC-options: -Wall -rtsopts+ Default-language: Haskell2010+ HS-source-dirs: tests+ Main-is: Main.hs+ Other-modules: Robotics.NXT.Basic
remote/remote.nxc view
@@ -1,137 +1,137 @@-#define DEBUG 0 - -#define INBOX 1 - -#define MOVE_FOR 6 -#define SET_TO 7 - -#define OUTPUT_A 1 -#define OUTPUT_B 2 -#define OUTPUT_C 4 - -#if DEBUG -inline string portsToString(unsigned char &ports) { - string s = ""; - if (ports & OUTPUT_A) strcat(s, "A"); - if (ports & OUTPUT_B) strcat(s, "B"); - if (ports & OUTPUT_C) strcat(s, "C"); - return s; -} -#endif - -inline void reset(const byte port) { - SetOutput(port, UpdateFlags, UF_UPDATE_RESET_COUNT | UF_UPDATE_RESET_BLOCK_COUNT | UF_UPDATE_RESET_ROTATION_COUNT); -} - -inline void output_reset(const byte port, char &power, unsigned long &limit) { - SetOutput(port, Power, power, TachoLimit, limit, OutputMode, OUT_MODE_MOTORON | OUT_MODE_BRAKE, RegMode, OUT_REGMODE_IDLE, RunState, OUT_RUNSTATE_RUNNING, UpdateFlags, UF_UPDATE_MODE | UF_UPDATE_SPEED | UF_UPDATE_TACHO_LIMIT | UF_UPDATE_RESET_BLOCK_COUNT | UF_UPDATE_RESET_ROTATION_COUNT); -} - -inline void output_reset_all(const byte port, char &power, unsigned long &limit) { - SetOutput(port, Power, power, TachoLimit, limit, OutputMode, OUT_MODE_MOTORON | OUT_MODE_BRAKE, RegMode, OUT_REGMODE_IDLE, RunState, OUT_RUNSTATE_RUNNING, UpdateFlags, UF_UPDATE_MODE | UF_UPDATE_SPEED | UF_UPDATE_TACHO_LIMIT | UF_UPDATE_RESET_BLOCK_COUNT | UF_UPDATE_RESET_ROTATION_COUNT | UF_UPDATE_RESET_COUNT); -} - -inline void output_absolute(const byte port, char &power, long &count, long &old_count) { - long target = count - old_count; - unsigned long limit = abs(target); - power *= sign(target); - old_count = count; - output_reset(port, power, limit); -} - -task main() { - unsigned char command, ports; - char power; - long old_count = 0; // TODO: Should we check this? Reset all counters at the beginning? Set it to tacho count? - - RandomNumberType random; - KeepAliveType keepalive; - - MessageReadType args; - args.QueueID = INBOX; - args.Remove = true; - while (true) { - #if DEBUG - TextOut(0, LCD_LINE6, " "); - TextOut(0, LCD_LINE6, StrCat("A ", NumToStr(MotorTachoCount(OUT_A)))); - TextOut(0, LCD_LINE7, " "); - TextOut(0, LCD_LINE7, StrCat("B ", NumToStr(MotorTachoCount(OUT_B)))); - TextOut(0, LCD_LINE8, " "); - TextOut(0, LCD_LINE8, StrCat("C ", NumToStr(MotorTachoCount(OUT_C)))); - #endif - - SysMessageRead(args); - if (args.Result != NO_ERR) continue; - - command = StrToNum(MidStr(args.Message, 0, 1)); - ports = StrToNum(MidStr(args.Message, 1, 1)); - power = StrToNum(MidStr(args.Message, 2, 3)) - 100; - - if (command == MOVE_FOR) { - unsigned long limit = StrToNum(MidStr(args.Message, 5, 6)); - - #if DEBUG - TextOut(0, LCD_LINE1, " "); - TextOut(0, LCD_LINE1, "MOVE_FOR"); - TextOut(0, LCD_LINE2, " "); - TextOut(0, LCD_LINE2, portsToString(ports)); - TextOut(0, LCD_LINE3, " "); - TextOut(0, LCD_LINE3, NumToStr(power)); - TextOut(0, LCD_LINE4, " "); - TextOut(0, LCD_LINE4, NumToStr(limit)); - #endif - - SysRandomNumber(random); - - // We randomly select order so that possible latencies are averaged out - if (random.Result & 1) { // Tests one bit for two choices - if (ports & OUTPUT_A) reset(OUT_A); - if (ports & OUTPUT_B) reset(OUT_B); - if (ports & OUTPUT_C) reset(OUT_C); - - if (ports & OUTPUT_A) output_reset_all(OUT_A, power, limit); - if (ports & OUTPUT_B) output_reset_all(OUT_B, power, limit); - if (ports & OUTPUT_C) output_reset_all(OUT_C, power, limit); - } - else { - if (ports & OUTPUT_C) reset(OUT_C); - if (ports & OUTPUT_B) reset(OUT_B); - if (ports & OUTPUT_A) reset(OUT_A); - - if (ports & OUTPUT_C) output_reset_all(OUT_C, power, limit); - if (ports & OUTPUT_B) output_reset_all(OUT_B, power, limit); - if (ports & OUTPUT_A) output_reset_all(OUT_A, power, limit); - } - } - else if (command == SET_TO) { - long count = StrToNum(MidStr(args.Message, 5, 6)); - - #if DEBUG - TextOut(0, LCD_LINE1, " "); - TextOut(0, LCD_LINE1, "SET_TO"); - TextOut(0, LCD_LINE2, " "); - TextOut(0, LCD_LINE2, portsToString(ports)); - TextOut(0, LCD_LINE3, " "); - TextOut(0, LCD_LINE3, NumToStr(power)); - TextOut(0, LCD_LINE4, " "); - TextOut(0, LCD_LINE4, NumToStr(count)); - #endif - - SysRandomNumber(random); - - // We randomly select order so that possible latencies are averaged out - if (random.Result & 1) { // Tests one bit for two choices - if (ports & OUTPUT_A) output_absolute(OUT_A, power, count, old_count); - if (ports & OUTPUT_B) output_absolute(OUT_B, power, count, old_count); - if (ports & OUTPUT_C) output_absolute(OUT_C, power, count, old_count); - } - else { - if (ports & OUTPUT_C) output_absolute(OUT_C, power, count, old_count); - if (ports & OUTPUT_B) output_absolute(OUT_B, power, count, old_count); - if (ports & OUTPUT_A) output_absolute(OUT_A, power, count, old_count); - } - } - - SysKeepAlive(keepalive); - } -} +#define DEBUG 0++#define INBOX 1++#define MOVE_FOR 6+#define SET_TO 7++#define OUTPUT_A 1+#define OUTPUT_B 2+#define OUTPUT_C 4++#if DEBUG+inline string portsToString(unsigned char &ports) {+ string s = "";+ if (ports & OUTPUT_A) strcat(s, "A");+ if (ports & OUTPUT_B) strcat(s, "B");+ if (ports & OUTPUT_C) strcat(s, "C");+ return s;+}+#endif++inline void reset(const byte port) {+ SetOutput(port, UpdateFlags, UF_UPDATE_RESET_COUNT | UF_UPDATE_RESET_BLOCK_COUNT | UF_UPDATE_RESET_ROTATION_COUNT);+}++inline void output_reset(const byte port, char &power, unsigned long &limit) {+ SetOutput(port, Power, power, TachoLimit, limit, OutputMode, OUT_MODE_MOTORON | OUT_MODE_BRAKE, RegMode, OUT_REGMODE_IDLE, RunState, OUT_RUNSTATE_RUNNING, UpdateFlags, UF_UPDATE_MODE | UF_UPDATE_SPEED | UF_UPDATE_TACHO_LIMIT | UF_UPDATE_RESET_BLOCK_COUNT | UF_UPDATE_RESET_ROTATION_COUNT);+}++inline void output_reset_all(const byte port, char &power, unsigned long &limit) {+ SetOutput(port, Power, power, TachoLimit, limit, OutputMode, OUT_MODE_MOTORON | OUT_MODE_BRAKE, RegMode, OUT_REGMODE_IDLE, RunState, OUT_RUNSTATE_RUNNING, UpdateFlags, UF_UPDATE_MODE | UF_UPDATE_SPEED | UF_UPDATE_TACHO_LIMIT | UF_UPDATE_RESET_BLOCK_COUNT | UF_UPDATE_RESET_ROTATION_COUNT | UF_UPDATE_RESET_COUNT);+}++inline void output_absolute(const byte port, char &power, long &count, long &old_count) {+ long target = count - old_count;+ unsigned long limit = abs(target); + power *= sign(target);+ old_count = count;+ output_reset(port, power, limit); +}++task main() {+ unsigned char command, ports;+ char power;+ long old_count = 0; // TODO: Should we check this? Reset all counters at the beginning? Set it to tacho count?+ + RandomNumberType random;+ KeepAliveType keepalive;++ MessageReadType args;+ args.QueueID = INBOX;+ args.Remove = true;+ while (true) {+ #if DEBUG+ TextOut(0, LCD_LINE6, " ");+ TextOut(0, LCD_LINE6, StrCat("A ", NumToStr(MotorTachoCount(OUT_A))));+ TextOut(0, LCD_LINE7, " ");+ TextOut(0, LCD_LINE7, StrCat("B ", NumToStr(MotorTachoCount(OUT_B))));+ TextOut(0, LCD_LINE8, " ");+ TextOut(0, LCD_LINE8, StrCat("C ", NumToStr(MotorTachoCount(OUT_C))));+ #endif+ + SysMessageRead(args);+ if (args.Result != NO_ERR) continue;+ + command = StrToNum(MidStr(args.Message, 0, 1));+ ports = StrToNum(MidStr(args.Message, 1, 1));+ power = StrToNum(MidStr(args.Message, 2, 3)) - 100;+ + if (command == MOVE_FOR) {+ unsigned long limit = StrToNum(MidStr(args.Message, 5, 6));++ #if DEBUG+ TextOut(0, LCD_LINE1, " ");+ TextOut(0, LCD_LINE1, "MOVE_FOR");+ TextOut(0, LCD_LINE2, " ");+ TextOut(0, LCD_LINE2, portsToString(ports));+ TextOut(0, LCD_LINE3, " ");+ TextOut(0, LCD_LINE3, NumToStr(power));+ TextOut(0, LCD_LINE4, " ");+ TextOut(0, LCD_LINE4, NumToStr(limit));+ #endif++ SysRandomNumber(random);+ + // We randomly select order so that possible latencies are averaged out+ if (random.Result & 1) { // Tests one bit for two choices+ if (ports & OUTPUT_A) reset(OUT_A);+ if (ports & OUTPUT_B) reset(OUT_B);+ if (ports & OUTPUT_C) reset(OUT_C);++ if (ports & OUTPUT_A) output_reset_all(OUT_A, power, limit);+ if (ports & OUTPUT_B) output_reset_all(OUT_B, power, limit);+ if (ports & OUTPUT_C) output_reset_all(OUT_C, power, limit);+ }+ else {+ if (ports & OUTPUT_C) reset(OUT_C);+ if (ports & OUTPUT_B) reset(OUT_B);+ if (ports & OUTPUT_A) reset(OUT_A);+ + if (ports & OUTPUT_C) output_reset_all(OUT_C, power, limit);+ if (ports & OUTPUT_B) output_reset_all(OUT_B, power, limit);+ if (ports & OUTPUT_A) output_reset_all(OUT_A, power, limit);+ }+ }+ else if (command == SET_TO) {+ long count = StrToNum(MidStr(args.Message, 5, 6));+ + #if DEBUG+ TextOut(0, LCD_LINE1, " ");+ TextOut(0, LCD_LINE1, "SET_TO");+ TextOut(0, LCD_LINE2, " ");+ TextOut(0, LCD_LINE2, portsToString(ports));+ TextOut(0, LCD_LINE3, " ");+ TextOut(0, LCD_LINE3, NumToStr(power));+ TextOut(0, LCD_LINE4, " ");+ TextOut(0, LCD_LINE4, NumToStr(count));+ #endif+ + SysRandomNumber(random);+ + // We randomly select order so that possible latencies are averaged out+ if (random.Result & 1) { // Tests one bit for two choices+ if (ports & OUTPUT_A) output_absolute(OUT_A, power, count, old_count);+ if (ports & OUTPUT_B) output_absolute(OUT_B, power, count, old_count);+ if (ports & OUTPUT_C) output_absolute(OUT_C, power, count, old_count);+ }+ else {+ if (ports & OUTPUT_C) output_absolute(OUT_C, power, count, old_count);+ if (ports & OUTPUT_B) output_absolute(OUT_B, power, count, old_count);+ if (ports & OUTPUT_A) output_absolute(OUT_A, power, count, old_count);+ }+ }+ + SysKeepAlive(keepalive);+ }+}