simulavr-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Simulavr-devel] Add example python script to simulate UART


From: Kevin O'Connor
Subject: [Simulavr-devel] Add example python script to simulate UART
Date: Fri, 15 Aug 2014 20:13:06 -0400
User-agent: Mutt/1.5.23 (2014-03-12)

Hi,

I put together a python script that can read/write to UART pins in
simulavr and display the results.  This is similar to the code in
src/ui/serial?x.cpp, but it is entirely contained in a single python
script (it doesn't require additional C code or TCL).

It took me a while to figure out how to do this, so I thought I would
send it to the list in case others need to implement similar
functionality.  I'm sending it in the form of a patch to the existing
simple_serial example.

Cheers,
-Kevin


>From 61144e2da027d8d92e823687d705363a62b8f6d4 Mon Sep 17 00:00:00 2001
From: Kevin O'Connor <address@hidden>
Date: Fri, 15 Aug 2014 19:46:20 -0400
Subject: [PATCH] Update simple_serial example with python script to simulate
 UART.

The current simple_serial example provides AVR C code that accesses
the hardware UART.  However, it doesn't provide a mechanism for
displaying the serial data outside of simulavr.  This patch adds a
simple python script that can run the binary, display data received
from the UART, and send data to the UART.
---
 examples/simple_serial/Makefile.am      |  2 +-
 examples/simple_serial/README           |  2 +-
 examples/simple_serial/simple_serial.py | 99 +++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+), 2 deletions(-)
 create mode 100644 examples/simple_serial/simple_serial.py

diff --git a/examples/simple_serial/Makefile.am 
b/examples/simple_serial/Makefile.am
index bebf7a7..f5a3de2 100644
--- a/examples/simple_serial/Makefile.am
+++ b/examples/simple_serial/Makefile.am
@@ -21,7 +21,7 @@ CLEANFILES = $(EXAMPLE).hex $(EXAMPLE).elf $(AVR_OBJS)
 
 
 do: $(EXAMPLE).elf
-       ../../src/simulavr $(SIMULAVR_ARGS)
+       PYTHONPATH=../../src @PYTHON@ simple_serial.py $(AVR_CPU) $< 
$(AVR_FREQUENCY)
 
 program: $(EXAMPLE).hex
        avrdude -c stk500v2 -b 115200 -p $(AVR_CPU) -P $(SERIAL_AVR) \
diff --git a/examples/simple_serial/README b/examples/simple_serial/README
index 9456914..d606d54 100644
--- a/examples/simple_serial/README
+++ b/examples/simple_serial/README
@@ -26,7 +26,7 @@ Building and running the example:
 
       make
 
- - Run the example:
+ - Run the example (this requires python to be enabled):
 
       make do
 
diff --git a/examples/simple_serial/simple_serial.py 
b/examples/simple_serial/simple_serial.py
new file mode 100644
index 0000000..b1e738b
--- /dev/null
+++ b/examples/simple_serial/simple_serial.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# Script to interact with simulavr by simulating a serial port.
+import sys
+import pysimulavr
+
+SERIALBITS = 10 # 8N1 = 1 start, 8 data, 1 stop
+BAUD = 19200
+
+# Class to read serial data from AVR serial transmit pin.
+class SerialRxPin(pysimulavr.PySimulationMember, pysimulavr.Pin):
+    def __init__(self):
+        pysimulavr.Pin.__init__(self)
+        pysimulavr.PySimulationMember.__init__(self)
+        self.sc = pysimulavr.SystemClock.Instance()
+        self.delay = 10**9 / BAUD
+        self.current = 0
+        self.pos = -1
+    def SetInState(self, pin):
+        pysimulavr.Pin.SetInState(self, pin)
+        self.state = pin.outState
+        if self.pos < 0 and pin.outState == pin.LOW:
+            self.pos = 0
+            self.sc.Add(self)
+    def DoStep(self, trueHwStep):
+        ishigh = self.state == self.HIGH
+        self.current |= ishigh << self.pos
+        self.pos += 1
+        if not self.pos:
+            return int(self.delay * 1.5)
+        if self.pos >= SERIALBITS:
+            self.handleChar(chr((self.current >> 1) & 0xff))
+            self.pos = -1
+            self.current = 0
+            return -1
+        return self.delay
+    def handleChar(self, c):
+        sys.stdout.write(c)
+        sys.stdout.flush()
+
+# Class to send serial data to AVR serial receive pin.
+class SerialTxPin(pysimulavr.PySimulationMember, pysimulavr.Pin):
+    def __init__(self):
+        pysimulavr.Pin.__init__(self)
+        pysimulavr.PySimulationMember.__init__(self)
+        self.SetPin('H')
+        self.sc = pysimulavr.SystemClock.Instance()
+        self.delay = 10**9 / BAUD
+        self.current = 0
+        self.pos = 0
+        self.queue = ""
+    def DoStep(self, trueHwStep):
+        if not self.pos:
+            if not self.queue:
+                return -1
+            self.current = (ord(self.queue[0]) << 1) | 0x200
+            self.queue = self.queue[1:]
+        newstate = 'L'
+        if self.current & (1 << self.pos):
+            newstate = 'H'
+        self.SetPin(newstate)
+        self.pos += 1
+        if self.pos >= SERIALBITS:
+            self.pos = 0
+        return self.delay
+    def pushChars(self, c):
+        queueEmpty = not self.queue
+        self.queue += c
+        if queueEmpty:
+            self.sc.Add(self)
+
+def main():
+    proc, elffile, speed = sys.argv[1:]
+
+    # launch simulator
+    sc = pysimulavr.SystemClock.Instance()
+    dev = pysimulavr.AvrFactory.instance().makeDevice(proc)
+    dev.Load(elffile)
+    dev.SetClockFreq(10**9 / int(speed))
+    sc.Add(dev)
+
+    # Setup rx pin
+    rxpin = SerialRxPin()
+    net = pysimulavr.Net()
+    net.Add(rxpin)
+    net.Add(dev.GetPin("D1"))
+
+    # Setup tx pin
+    txpin = SerialTxPin()
+    net2 = pysimulavr.Net()
+    net2.Add(dev.GetPin("D0"))
+    net2.Add(txpin)
+
+    # Run loop
+    sc.RunTimeRange(200000)
+    txpin.pushChars("Sending data...")
+    sc.RunTimeRange(400000000)
+
+if __name__ == '__main__':
+    main()
-- 
1.9.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]