finished live CLI, BB firmware improvements and fixes

Sun, 11 Dec 2011 17:34:40 +0100

author
Malte Bayer <mbayer@neo-soft.org>
date
Sun, 11 Dec 2011 17:34:40 +0100
changeset 77
cede78304992
parent 76
1c8305764b3f
child 78
d9126a55295c

finished live CLI, BB firmware improvements and fixes

blackbox/main.c file | annotate | diff | comparison | revisions
slotUI/SlotCli.py file | annotate | diff | comparison | revisions
slotUI/freeslot.py file | annotate | diff | comparison | revisions
--- a/blackbox/main.c	Sun Dec 11 13:54:14 2011 +0100
+++ b/blackbox/main.c	Sun Dec 11 17:34:40 2011 +0100
@@ -102,7 +102,7 @@
         16 stopbit
     */
 
-    /* PITLANE STATUS DEFINITION
+    /* PITLANE/TRACKSWITCH STATUS DEFINITION
         1 = AA
         2 = AB
         3 = BB
@@ -113,6 +113,8 @@
 
 #define STARTSTOP 0b1000000000000001
 void decode_responsewire(void) {
+    // ATTENTION: THIS IS CALLED IN AN INTERRUPT, KEEP AS SHORT AS POSSIBLE
+
     uint16_t data = responsewire_data;
     // first check if start + stopbit are set
     // todo future: unsure but last bit doesnt get set?!
@@ -123,27 +125,32 @@
     }
 */
     // now extract the car id, track change status
-    uint8_t car = ((data >> 1) & 0b111);
-    uint8_t status = ((data >> 4) & 0b1111);
-    uint8_t sender = ((data >> 8) & 0b1111);
-    uint8_t type = ((data >> 12) & 0b111);
+    data >>= 1;
+    uint8_t car = (data & 0b111);
+    data >>= 3;
+    uint8_t status = (data & 0b1111);
+    data >>= 4;
+    uint8_t sender = (data & 0b1111);
+    data >>= 4;
+    uint8_t type = (data & 0b111);
     if (type == 4) {
         // pitlane response
         if (status == 5) slot[car].canrefuel = 1;
         if (status == 6) for (data=0; data<MAX_SLOTS; data++) slot[data].canrefuel = 0;
     }
     RS232_puts("RW:");
-    itoa(car, s, 16);
-    RS232_puts(s);
+    RS232_putc(car + '0');
     RS232_putc(':');
-    itoa(type, s, 16);
-    RS232_puts(s);
+    RS232_putc(type + '0');
     RS232_putc(':');
     itoa(sender, s, 16);
     RS232_puts(s);
     RS232_putc(':');
     itoa(status, s, 16);
     RS232_puts(s);
+    RS232_putc(':');
+    ultoa(sysclk.value, s, 16);
+    RS232_puts(s);
     RS232_putc('\n');
 }
 
@@ -429,6 +436,8 @@
         slot[i].seccnt = 0;
         slot[i].accel = 15; // full acceleration per default - TODO
         slot[i].canrefuel = 0;
+        slot[i].lap_time_start.value = 0;
+        slot[i].lap_time.value = 0;
     }
     sysclk.value = 0;
 }
@@ -468,10 +477,7 @@
                 if (slot[car0-1].lap_time_start.value != 0) {
                     slot[car0-1].lap_time.value = diff.value;
                     slot[car0-1].laps++;
-                    RS232_putc('L');
-                    RS232_putc(':');
-                    RS232_putc('B');
-                    RS232_putc(':');
+                    RS232_puts("L:3:"); // 3 = BB
                     itoa(slot[car0-1].laps, s, 16);
                     RS232_puts(s);
                     RS232_putc(':');
@@ -479,6 +485,9 @@
                     RS232_putc(':');
                     ultoa(diff.value, s, 16);
                     RS232_puts(s);
+                    RS232_putc(':');
+                    ultoa(clk.value, s, 16);
+                    RS232_puts(s);
                     RS232_putc('\n');
                 }
                 slot[car0-1].lap_time_start.value = clk.value;
@@ -494,10 +503,7 @@
                 if (slot[car1-1].lap_time_start.value != 0) {
                     slot[car1-1].lap_time.value = diff.value;
                     slot[car1-1].laps++;
-                    RS232_putc('L');
-                    RS232_putc(':');
-                    RS232_putc('A');
-                    RS232_putc(':');
+                    RS232_puts("L:1:"); // 1 = AA
                     itoa(slot[car1-1].laps, s, 16);
                     RS232_puts(s);
                     RS232_putc(':');
@@ -505,6 +511,9 @@
                     RS232_putc(':');
                     ultoa(diff.value, s, 16);
                     RS232_puts(s);
+                    RS232_putc(':');
+                    ultoa(clk.value, s, 16);
+                    RS232_puts(s);
                     RS232_putc('\n');
                 }
                 slot[car1-1].lap_time_start.value = clk.value;
@@ -524,6 +533,9 @@
         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;
@@ -554,9 +566,9 @@
         if (response_len > 0) {
             itoa(response, s, 2);
             response_len = 0;
-            RS232_puts("ANSWER RX: ");
-            RS232_puts(s);
-            RS232_putc('\n');
+            //RS232_puts("ANSWER RX: ");
+            //RS232_puts(s);
+            //RS232_putc('\n');
         }
 
 
--- a/slotUI/SlotCli.py	Sun Dec 11 13:54:14 2011 +0100
+++ b/slotUI/SlotCli.py	Sun Dec 11 17:34:40 2011 +0100
@@ -4,19 +4,23 @@
 Command line interface
 """
 
-from freeslot import Blackbox
+from freeslot import Blackbox, LOGLEVEL
 from optparse import OptionParser
+from operator import itemgetter
 import sys
 from copy import copy
 import curses
 
-VERSION = "1.2"
+VERSION = "1.3"
 MAXSLOTS = 6
 TERM = {
     "caption": "\033[1;37m\033[1;44m",
     "text": "\033[1;30m",
     }
 
+# disable debug log output
+LOGLEVEL = 10
+
 class SlotCli():
     def __init__(self):
         self.box = Blackbox()
@@ -29,6 +33,9 @@
             "fuel": 0,
             "position": 0,
             "drive": 0,
+            "status": "Idle",
+            "clk": 0,
+            "car": 0,
             }
 
         self.slot = [
@@ -36,26 +43,47 @@
             copy(self.slot_dummy), copy(self.slot_dummy),
             copy(self.slot_dummy), copy(self.slot_dummy),
             ]
+        self.reset_slots()
+        self.sysclk = 0.00
+
+    def reset_slots(self):
+        idx = 0
+        for slt in self.slot:
+            slt["laps"] = 0
+            slt["last"] = 0.00
+            slt["best"] = 0.00
+            slt["fuel"] = 0
+            slt["position"] = idx
+            slt["car"] = idx # used for sort order calculation
+            slt["status"] = self.slot_dummy["status"]
+            slt["clk"] = 0
+            idx += 1
 
     def update_positions(self):
-        for idx in range(MAXSLOTS):
-            self.slot[idx]["position"] = idx + 1
-        # TODO
+        order1 = sorted(self.slot, key=itemgetter(
+            "clk"))
+        order2 = sorted(self.slot, key=itemgetter(
+            "laps"), reverse=True)
+        idx = 1
+        for tst in order2:
+            self.slot[tst["car"]]["position"] = idx
+            idx += 1
 
     def render_slots(self):
         self.update_positions()
         self.scr.addstr(3,0,
-            "Pos | #/Name          | Laps | Best   | Last   | Fuel |",
+            "Pos | #/Name            | Laps | Best     | Last     | Fuel | Status    ",
             curses.color_pair(2))
         for idx in range(MAXSLOTS):
             self.scr.addstr((3 + self.slot[idx]["position"]), 0,
-                "%3i | %15s | %4i | %5.2fs | %5.2fs | %3i%% |" % (
+                "%3i | %i %15s | %4i | %7.2fs | %7.2fs | %3i%% | %10s" % (
                 self.slot[idx]["position"],
-                self.slot[idx]["name"],
+                self.slot[idx]["car"] + 1, self.slot[idx]["name"],
                 self.slot[idx]["laps"],
                 self.slot[idx]["best"],
                 self.slot[idx]["last"],
                 self.slot[idx]["fuel"],
+                self.slot[idx]["status"],
                 ) )
 
     def cleartop(self):
@@ -90,6 +118,9 @@
         Live Monitor on the console
         Keyboard loop to control it???
         """
+        # clear garbage in UART rx buffer
+        while self.box.com.readline() != "": pass
+
         self.monitor_init()
         self.scr = curses.initscr()
         curses.start_color()
@@ -132,17 +163,22 @@
             # is there something in the rx buffer?
             rx = self.box.com.readline()
             if rx != "":
+                self.scr.addstr(10,0,
+                    "Last RX: %19s" % rx, curses.color_pair(2))
+                self.scr.refresh()
                 # we have received something
                 data = rx.split(":")
                 if rx[:2] == "L:":
                     # update lap time info
+                    l = int(data[2], 16)
                     slot = int(data[3]) - 1
-                    t = int(data[4], 16)
-                    l = int(data[2], 16)
-                    t /= 2000.00
+                    t = int(data[4], 16) / 2000.00
+                    self.sysclk = int(data[5], 16) / 2000.00
                     self.slot[slot]["laps"] = l
                     self.slot[slot]["last"] = t
+                    self.slot[slot]["clk"] = self.sysclk
                     if (self.slot[slot]["best"] > t) or (self.slot[slot]["best"] == 0): self.slot[slot]["best"] = t
+                    self.slot[slot]["status"] = "IN-RACE"
                     self.render_slots()
 
                 if rx[:2] == "F:":
@@ -150,9 +186,51 @@
                     slot = int(data[1])
                     f = int(data[2], 16)
                     f = f / 100 # fuel in percent
+                    self.sysclk = int(data[3], 16) / 2000.00
                     self.slot[slot]["fuel"] = f
                     self.render_slots()
 
+                if rx[:1] == "~":
+                    # jumpstart occured
+                    slot = int(rx[1:2])
+                    t = int(data[1], 16) / 2000.00
+                    self.slot[slot]["jumpstart"] = t
+                    self.slot[slot]["status"] = "Jumpstart!"
+
+                if rx[:3] == "RW:":
+                    # ResponseWire packet, do nothing at the moment, just decode
+                    slot = int(data[1])
+                    devtype = int(data[2])
+                    sender = int(data[3], 16)
+                    status = int(data[4], 16)
+                    self.sysclk = int(data[5], 16)
+                    if (devtype == 4):
+                        # pitlane sent something
+                        if (status == 5): self.slot[slot]["status"] = "PITLANE"
+                        if (status == 6): self.slot[slot]["status"] = "IN-RACE"
+
+                    self.render_slots()
+
+                if rx == "!RACE PREPARE":
+                    # reset current race status
+                    # and display PREPARE PHASE
+                    for slot in range(MAXSLOTS):
+                        self.slot[slot]["status"] = "Prepare"
+
+                if rx == "!RACE START":
+                    for slot in range(MAXSLOTS):
+                        if self.slot[slot]["status"] == "~~~~~~~~~~":
+                            self.slot[slot]["status"] = "Idle"
+
+                if rx == "!COUNTDOWN":
+                    # countdown initiated
+                    for slot in range(MAXSLOTS):
+                        self.slot[slot]["status"] = "~~~~~~~~~~"
+
+                self.scr.addstr(10,31,
+                    "Race Timer: %7.3f min" % (self.sysclk / 60),
+                    curses.color_pair(2))
+
                 self.scr.refresh()
 
         # terminate
--- a/slotUI/freeslot.py	Sun Dec 11 13:54:14 2011 +0100
+++ b/slotUI/freeslot.py	Sun Dec 11 17:34:40 2011 +0100
@@ -10,11 +10,12 @@
 
 # define loglevels
 DEBUG = 20
+LOGLEVEL = 20
 def log(level, msg):
     """
     Logging output function
     """
-    print msg
+    if level <= LOGLEVEL: print msg
 
 class SerialCommunicator():
     def __init__(self, device, speed):

mercurial