added learn and teach modes for intelligent ghostcars

Sun, 28 Oct 2012 16:18:53 +0100

author
Malte Bayer <mbayer@neo-soft.org>
date
Sun, 28 Oct 2012 16:18:53 +0100
changeset 103
52fd4283cd2c
parent 102
72f5eb420096
child 104
95b2c23cb973

added learn and teach modes for intelligent ghostcars

blackbox/Makefile file | annotate | diff | comparison | revisions
blackbox/driver/rs232.c file | annotate | diff | comparison | revisions
blackbox/driver/rs232.h file | annotate | diff | comparison | revisions
blackbox/main.c file | annotate | diff | comparison | revisions
blackbox/main.h file | annotate | diff | comparison | revisions
slotUI/SlotCli.py file | annotate | diff | comparison | revisions
--- a/blackbox/Makefile	Sun Oct 28 11:23:18 2012 +0100
+++ b/blackbox/Makefile	Sun Oct 28 16:18:53 2012 +0100
@@ -81,6 +81,9 @@
 program: code
 	$(AVRDUDE) -P $(PORT) -c stk500v2 -b $(ISP_BAUD) -i 1 -p $(MCU) -V -U flash:w:$(PRG).hex:i
 
+backup:
+	$(AVRDUDE) -P $(PORT) -c stk500v2 -b $(ISP_BAUD) -i 1 -p $(MCU) -V -U flash:r:$(PRG)_backup.hex:i
+
 fuse:
 	$(AVRDUDE) -P $(PORT) -c stk500v2 -p $(MCU) -V $(FUSES)
 
--- a/blackbox/driver/rs232.c	Sun Oct 28 11:23:18 2012 +0100
+++ b/blackbox/driver/rs232.c	Sun Oct 28 16:18:53 2012 +0100
@@ -48,7 +48,7 @@
     //RS232_txc();
 }
 
-void RS232_puts_p(char* s) {
+void RS232_puts_p(const char* s) {
     char c=pgm_read_byte(s);
     while (c != 0) {
         // send char
--- a/blackbox/driver/rs232.h	Sun Oct 28 11:23:18 2012 +0100
+++ b/blackbox/driver/rs232.h	Sun Oct 28 16:18:53 2012 +0100
@@ -6,7 +6,7 @@
 extern void RS232_init(void);
 extern void RS232_putc(char c);
 extern void RS232_puts(char* s);
-extern void RS232_puts_p(char* s);
+extern void RS232_puts_p(const char* s);
 
 
 #endif
\ No newline at end of file
--- a/blackbox/main.c	Sun Oct 28 11:23:18 2012 +0100
+++ b/blackbox/main.c	Sun Oct 28 16:18:53 2012 +0100
@@ -13,15 +13,15 @@
 #include "main.h"
 #include "lowlevel.h"
 
-char ok[]               PROGMEM="OK\n";
-char busy[]             PROGMEM="BUSY\n";
-char prepare[]          PROGMEM="!RACE PREPARE\n";
-char countdownstart[]   PROGMEM="!COUNTDOWN\n";
-char racestart[]        PROGMEM="!RACE START\n";
+const char ok[]               PROGMEM="OK\n";
+const char busy[]             PROGMEM="BUSY\n";
+const char prepare[]          PROGMEM="!RACE PREPARE\n";
+const char countdownstart[]   PROGMEM="!COUNTDOWN\n";
+const char racestart[]        PROGMEM="!RACE START\n";
 
-char SHORTCUT[]         PROGMEM="!SHORTCUT\n";
-char PANIC[]            PROGMEM="!PANIC\n";
-char RESUME[]           PROGMEM="!RESUME\n";
+const char SHORTCUT[]         PROGMEM="!SHORTCUT\n";
+const char PANIC[]            PROGMEM="!PANIC\n";
+const char RESUME[]           PROGMEM="!RESUME\n";
 
 typedef union {
     uint32_t value;
@@ -40,9 +40,11 @@
     unsigned speedminimum:4; // 4bits speedminimum
     unsigned seccnt:4; // 4 bits tenth seconds counter
     unsigned accel:4; // 4 bits last configured acceleration
+    unsigned speed:4; // 4 bits last speed
     unsigned trackswitch:1; // 1bit bool
     unsigned canrefuel:1; // 1bit bool
     unsigned unlimitedfuel:1; // 1bit bool
+    unsigned trackchange:1; // 1bit bool
     uint16_t jumpstart_time, laps, fuel;
     u32 lap_time_start, lap_time;
 } cardata;
@@ -371,6 +373,8 @@
         }
     }
     speed = tmp;
+    slot[controller].speed = tmp;
+    slot[controller].trackchange = (trackchange != 0);
     tmp = tmp << 1;
     if (trackchange != 0) tmp |= (1<<5);
 
@@ -577,22 +581,35 @@
 
 void slot_liveinfo(uint8_t idx) {
     if (liveinfo == 0) return;
-    // increment packet counter, if == 10 output some live info
-    if (slot[idx].seccnt == 10) {
-        // output current fuel status
-        RS232_putc('F');
-        RS232_putc(':');
-        RS232_putc(idx + '0');
-        RS232_putc(':');
-        itoa(slot[idx].fuel, s, 16);
-        RS232_puts(s);
-        RS232_putc(':');
-        ultoa(sysclk.value, s, 16);
-        RS232_puts(s);
-        RS232_putc('\n');
 
-        slot[idx].seccnt = 0;
-    } else slot[idx].seccnt++;
+    if (liveinfo == 1) {
+        // increment packet counter, if == 10 output some live info
+        if (slot[idx].seccnt == 10) {
+            // output current fuel status
+            RS232_putc('F');
+            RS232_putc(':');
+            RS232_putc(idx + '0');
+            RS232_putc(':');
+            itoa(slot[idx].fuel, s, 16);
+            RS232_puts(s);
+            RS232_putc(':');
+            ultoa(sysclk.value, s, 16);
+            RS232_puts(s);
+            RS232_putc('\n');
+            slot[idx].seccnt = 0;
+        } else slot[idx].seccnt++;
+    } else if ( (liveinfo - 2) == idx ) {
+            // output controller status LIVEINFO-2 for remote learning
+            RS232_putc('L');
+            RS232_putc('N');
+            RS232_putc(':');
+            itoa(slot[idx].speed, s, 16);
+            RS232_puts(s);
+            RS232_putc(':');
+            if (slot[idx].trackchange)
+            RS232_putc('X');
+            RS232_putc('\n');
+    }
 }
 
 
--- a/blackbox/main.h	Sun Oct 28 11:23:18 2012 +0100
+++ b/blackbox/main.h	Sun Oct 28 16:18:53 2012 +0100
@@ -100,9 +100,9 @@
 extern uint8_t mode;
 extern uint8_t btn_start;
 extern uint8_t old_start;
-extern char SHORTCUT[];
-extern char PANIC[];
-extern char RESUME[];
+extern const char SHORTCUT[];
+extern const char PANIC[];
+extern const char RESUME[];
 
 // function prototypes
 void reset_vars(void);
--- a/slotUI/SlotCli.py	Sun Oct 28 11:23:18 2012 +0100
+++ b/slotUI/SlotCli.py	Sun Oct 28 16:18:53 2012 +0100
@@ -11,8 +11,9 @@
 import sys, os
 from copy import copy
 import curses
+from time import sleep
 
-VERSION = "1.6"
+VERSION = "1.7"
 MAXSLOTS = 6
 TERM = {
     "caption": "\033[1;37m\033[1;44m",
@@ -212,12 +213,104 @@
         return inp
 
 
-    def monitor_init(self):
+    def monitor_init(self, live = 1):
         """
         Send initializing commands for live monitoring
         """
         self.box.query("F1\n") # set fuel logic enabled
-        self.box.query("*1\n") # set live fuel info
+        self.box.query("*%i\n" % live) # set live fuel info
+
+    def monitor_learn(self, slot):
+        # clear garbage in UART rx buffer
+        self.box.query("*0\n") # set live fuel info
+        self.box.query("*0\n") # set live fuel info
+        while self.box.readline() != "": pass
+
+        trk = False
+        spd = 0
+        trk_old = False
+        spd_old = 0
+        clock = -1
+
+        self.monitor_init(slot + 2)
+        while 1:
+            #key = self.scr.getch()
+            #if key == ord('c'): break
+
+            # is there something in the rx buffer?
+            rx = self.box.readline()
+            if (rx != ""):
+                try:
+                    data = rx.split(":")
+                    if rx[:3] == "LN:":
+                        if clock >= 0:
+                            clock += 1
+                        spd = int(data[1], 16)
+                        trk = (data[2] != 'X')
+                        if (spd != spd_old) or (trk != trk_old):
+                            if clock < 0:
+                                clock = 0
+                            print "%i,%i,%s" % (clock, spd, trk)
+                        trk_old = trk
+                        spd_old = spd * 1
+                    if rx[:2] == "L:":
+                        # update lap time info
+                        l = int(data[2], 16)
+                        s = int(data[3]) - 1
+                        t = int(data[4], 16) / 2000.00
+                        if (slot == s):
+                            print "# lap %i complete: %3.2f seconds" % (l, t)
+                            clock = 0
+                            print "%i,%i,%s" % (clock, spd, trk)
+                except:
+                    print "RX ERROR: " % rx
+
+    def monitor_playback(self, slot, filename):
+        # clear garbage in UART rx buffer
+        self.box.query("*0\n") # set live fuel info
+        self.box.query("*0\n") # set live fuel info
+        sleep(1)
+        cli.box.speedminimum(slot, 0 )
+        while self.box.readline() != "": pass
+
+        clock = -5
+        trkfile = open(filename, "r").readlines()
+        print "Loading %s..." % filename
+
+        while 1:
+            try:
+                for l in trkfile:
+                    l = l.strip()
+                    if (l != "") and (l[:1] != "#"):
+                        print "Line: %s" % repr(l)
+                        data = l.split(",")
+                        speed = int(data[1])
+                        while (clock < int(data[0]) and (int(data[0]) > 0)):
+                            clock += 1
+                            sleep(0.07)
+                        print "CLK %i/%i -> set: %i" % (clock, int(data[0]), speed)
+                        cli.box.speedminimum(slot, speed )
+                # now wait for lap sync :)
+                while self.box.readline() != "": pass
+                rx = ""
+                while rx[:2] != "L:":
+                    rx = self.box.readline()
+                data = rx.split(":")
+                l = int(data[2], 16)
+                s = int(data[3]) - 1
+                t = int(data[4], 16) / 2000.00
+                print "# lap %i complete: %3.2f seconds" % (l, t)
+                clock = -3
+            except Exception, e:
+                print repr(e)
+                sys.exit(1)
+            except KeyboardInterrupt:
+                print "resetting"
+                cli.box.speedminimum(slot, 0 )
+                cli.box.speedminimum(slot, 0 )
+                sys.exit(0)
+                
+
 
     def monitor(self):
         """
@@ -450,6 +543,10 @@
     parser = OptionParser(version="%prog " + VERSION)
     parser.add_option("--live", dest="live", action="store_true", default=False,
         help="Run Live monitor on console", metavar="[0-5]")
+    parser.add_option("--learn", dest="learn", action="store_true", default=False,
+        help="Run Learning mode for [slot]", metavar="[0-5]")
+    parser.add_option("--teach", dest="playback", 
+        help="Playback teach file", metavar="[filename]")
 
     parser.add_option("--slot", dest="carid",
         help="Required for programming a car directly", metavar="[1-6]")
@@ -487,6 +584,16 @@
             print "Error: Invalid slot selected"
             sys.exit(1)
 
+    if options.learn:
+        # start the learn monitor
+        cli.monitor_learn(options.carid)
+        sys.exit(0)
+
+    if options.playback:
+        # start the playback monitor
+        cli.monitor_playback(options.carid, options.playback)
+        sys.exit(0)
+
     if options.fuel:
         print "setFuel: " + cli.box.progcar(int(options.carid), "fuel", int(options.fuel))
 

mercurial