simulavr-devel
[Top][All Lists]
Advanced

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

Re: [Simulavr-devel] SPI Device Support?


From: Joel Sherrill
Subject: Re: [Simulavr-devel] SPI Device Support?
Date: Wed, 18 Mar 2009 15:39:30 -0500
User-agent: Thunderbird 2.0.0.19 (X11/20090105)

Michael N. Moran wrote:
Joel Sherrill wrote:
Michael N. Moran wrote:
Joel Sherrill wrote:
And that brings up the next question.. Since I
have to simulate a TI ADS1258 SPI analog, does
anyone have any suggestions on how to hook a
simulated device on the SPI bus?
I submitted patches some years ago that are
still Open.

This patch contains some example code and
"stimulator" classes for stimulating the SPI
port using file I/O. The check.tcl file in
the examples/mnm directory shows how it is
all put together.

<https://savannah.nongnu.org/patch/?4599>

Note that it requires some previous
(still open) patches.

The last patch (still Open0 that I submitted
is here:

<https://savannah.nongnu.org/patch/?4629>

I hope this helps.

OK.  I have downloaded them and will
clean them up against the head.  Once I
get it building, I will post a new diff with
both merged if that's OK with you.

I'm speechless ;) Of course its OK with me.

I thought so.  It thrills me since I needed
SPI and analog support for my "real work"

Attached is a patch against the current CVS head.
It builds and seems to get close to running your
application.  I think the failure is related to
some parts of the patch which I think are missing.


+ The .6 patch modifies atmega48.cpp which
does not exist in CVS.

+ The .4 patch added this to main.cpp but I didn't
see any code to set or use the flags:

Index: src/main.cpp
===================================================================
RCS file: /sources/simulavr/simulavrxx/src/main.cpp,v
retrieving revision 1.23
diff -u -r1.23 main.cpp
--- src/main.cpp    13 Mar 2009 20:43:34 -0000    1.23
+++ src/main.cpp    18 Mar 2009 19:53:00 -0000
@@ -94,6 +94,10 @@
   string tracefilename("unknown");
   int global_gdbserver_port    = 1212;
   int global_gdb_debug         = 0;
+   bool use_spi_source=false;
+   bool use_spi_sink=false;
+   const char* pinmon = 0;
+
   bool globalWaitForGdbConnection=true; //please wait for gdb connection
   int userinterface_flag=0;
   unsigned long long fcpu=4000000;

I want you to test it.

It may take a while, but I'll make it happen.

:)
Thanks Joel




--
Joel Sherrill, Ph.D.             Director of Research & Development
address@hidden        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
  Support Available             (256) 722-9985


? 4-rej
? examples/spi/Makefile.notauto
Index: configure.ac
===================================================================
RCS file: /sources/simulavr/simulavrxx/configure.ac,v
retrieving revision 1.44
diff -u -r1.44 configure.ac
--- configure.ac        16 Mar 2009 17:50:36 -0000      1.44
+++ configure.ac        18 Mar 2009 20:37:42 -0000
@@ -120,6 +120,9 @@
     [examples/atmel_key/checkdebug.tcl],
     [chmod +x examples/atmel_key/checkdebug.tcl])
   AC_CONFIG_FILES(
+    [examples/spi/check.tcl],
+    [chmod +x examples/spi/check.tcl])
+  AC_CONFIG_FILES(
     [examples/stdiodemo/checkdebug.tcl],
     [chmod +x examples/stdiodemo/checkdebug.tcl])
 else
@@ -140,7 +143,8 @@
   regress/Makefile regress/modules/Makefile regress/test_opcodes/Makefile \
   regress/avrtest/Makefile \
   examples/Makefile examples/anacomp/Makefile examples/atmel_key/Makefile \
-  examples/simple_ex1/Makefile examples/stdiodemo/Makefile \
+  examples/simple_ex1/Makefile examples/spi/Makefile \
+  examples/stdiodemo/Makefile \
 ])
 AC_OUTPUT
 
Index: examples/Makefile.am
===================================================================
RCS file: /sources/simulavr/simulavrxx/examples/Makefile.am,v
retrieving revision 1.9
diff -u -r1.9 Makefile.am
--- examples/Makefile.am        16 Mar 2009 20:30:45 -0000      1.9
+++ examples/Makefile.am        18 Mar 2009 20:37:42 -0000
@@ -5,7 +5,7 @@
 
 SUBDIRS = simple_ex1 anacomp atmel_key
 if USE_TCL
-SUBDIRS += anacomp stdiodemo
+SUBDIRS += anacomp spi stdiodemo
 endif
 
 noinst_DATA = kbd.xbm
Index: examples/spi/.cvsignore
===================================================================
RCS file: examples/spi/.cvsignore
diff -N examples/spi/.cvsignore
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ examples/spi/.cvsignore     18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,4 @@
+Makefile
+Makefile.in
+check.tcl
+spi.elf
Index: examples/spi/Makefile.am
===================================================================
RCS file: examples/spi/Makefile.am
diff -N examples/spi/Makefile.am
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ examples/spi/Makefile.am    18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,32 @@
+#
+#  $Id: Makefile.am,v 1.12 2009/03/11 21:35:49 joelsherrill Exp $
+#
+
address@hidden@
+
+noinst_DATA = spi.elf
+
+CLEANFILES = spi.elf main.o trace
+
+EXTRA_DIST = main.cpp spidata anadata
+
+all-local: $(objdir)/spidata $(objdir)/anadata
+
+$(objdir)/spidata: $(srcdir)/spidata
+       test -r spidata || cp $(srcdir)/spidata spidata
+
+$(objdir)/anadata: $(srcdir)/anadata
+       test -r anadata || cp $(srcdir)/anadata anadata
+
+do: spi.elf
+       $(TCL_WISH) check.tcl
+
+# WAR: should detect avr-toolset first!
+
+main.o : $(srcdir)/main.cpp
+       $(AVR_GCC) -g -O2 -mmcu=atmega128 -c -o $@ $<
+
+spi.elf : main.o
+       $(AVR_GCC) -mmcu=atmega128 -o $@ $<
+
+SUBDIRS =
Index: examples/spi/README
===================================================================
RCS file: examples/spi/README
diff -N examples/spi/README
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ examples/spi/README 18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,92 @@
+#
+#  $Id$
+#
+
+Demonstrates the following Stimulation classes:
+
+       o SpiSink - monitors the /SS, SCLK and MISO pins and prints
+               each byte to stdout.
+
+       o SpiSource - drives the /SS, SCLK and MOSI pins with data from
+               the spidata file.
+
+       o PinMonitor - monitors Port A Bit 0 and prints changes in its
+               binary status to stdout.
+
+       o AdcPin - Stimulates Port F Bit 0 with the values contained
+               in the anadata file.
+
+The AVR program alternately (every other byte) echoes the byte received
+on the SPI or the ADCH value read from a recenet A/D converter, to the SPI.
+
+The spidata file contains an HDLC encoded stream of *mostly* flags
+that was used in my project at work. (We're running a form of
+PPP/HDLC over SPI.)
+
+The format of the spidata file consists of comments (lines
+that start with a '#') and data lines. Each data line consists
+of 3 values.
+
+o First Value - the value (0 or non-zero)of /SS
+o Second Value - the value (0 or non-zero) of SCLK
+o Third Value - the value (0 or non-zero) of MOSI
+
+When the SpiSource program stimulator reaches the end-of-file,
+it rewinds and repeats ad-nauseum.
+
+The anadata file contains analog data that that is read by the
+AdcPin class and written to the Port F Bit 0 analog input of
+the ATMega128.
+
+The format of the anadata file consists of comments (lines
+that start with a '#' character) and analog input lines.
+Each input line consists of 2 values separated by whitespace.
+
+o First Value - number of nano-seconds before the next value
+       is read and applied to the analog input.
+o Second Value - signed integer "analogValue" to be applied
+       to the analog input.
+
+To try it:
+
+Step 1:
+       Configure and build the simulavr (simulavr.so in particular)
+
+Step 2:
+       Build the AVR test program in this directory.
+       $ make
+
+Step 3:
+       Run the test TCL script from this directory.
+       $ check.tcl
+
+Step 4:
+       Marvel at the stdio activity.
+
+Step 5:
+       Try modifying the spidata file and see the results.
+
+
+What you'll see on stdout:
+
+Note: Comments added on the right.
+
+spisink: /SS asserted          ; SPI /SS goes LOW (printed by SpiSink)
+spisink: 0x00                          ; 0x00 byte received on MISO from AVR 
(printed by SpiSink)
+PORTA0: ASSERT                         ; Port A Bit 0 set low by AVR (printed 
by PinMonitor)
+spisink: 0x00                          ; Analog Data from AVR on SPI MISO
+spisink: 0x02                          ; echoed HDLC Data from AVR on SPI MISO
+spisink: 0x99                          ; Analog data from AVR on SPI MISO
+spisink: 0xD3                          ; echoed HDLC data from AVR on SPI MISO
+spisink: 0x66                          ; Analog data from AVR on SPI MISO
+spisink: 0x7E                          ; echoed HDLC data from AVR on SPI MISO
+spisink: 0x33                          ; Analog data from AVR on SPI MISO
+spisink: 0x7E                          ; echoed HDLC data from AVR on SPI MISO
+...
+...
+spisink: 0x7E                          ; echoed HDLC data from AVR on SPI MISO
+spisink: 0x04                          ; Analog data from AVR on SPI MISO
+spisink: /SS negated           ; SPI /SS goes HIGH (printed by SpiSink)
+spisink: /SS asserted          ; SPI /SS goes LOW (printed by SpiSink)
+spisink: 0x7E                          ; echoed HDLC data
+
Index: examples/spi/anadata
===================================================================
RCS file: examples/spi/anadata
diff -N examples/spi/anadata
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ examples/spi/anadata        18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,32 @@
+#
+# This is an analog pin data file. Each must be either a comment
+# or an analog entry with the format:
+#
+# <delayInNanoseconds> <signed analog integer value>
+#
+# The delay is the amount of time before the following line
+# is read and executed.
+#
+3333333  5000000
+3333333  4000000
+3333333  3000000
+3333333  2000000
+3333333  1000000
+3333333  900000
+3333333  800000
+3333333  700000
+3333333  600000
+3333333  500000
+3333333  400000
+3333333  300000
+3333333  200000
+3333333  100000
+3333333  90000
+3333333  80000
+3333333  70000
+3333333  60000
+3333333  50000
+3333333  40000
+3333333  30000
+3333333  20000
+3333333  10000
Index: examples/spi/check.tcl.in
===================================================================
RCS file: examples/spi/check.tcl.in
diff -N examples/spi/check.tcl.in
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ examples/spi/check.tcl.in   18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,84 @@
+#! @TCL_WISH@
+#
+#  $Id: check.tcl.in,v 1.6 2009/03/06 11:28:20 zfrdh Exp $
+#
+
+set traceFile trace
+
+#load the avr-simulator package
+load @top_builddir@/src/.libs/libsimulavr.so
+
+puts "simulavr loaded"
+
+#create new device
+set dev1 [new_AvrDevice_atmega128]
+
+#load elf file to the device 
+AvrDevice_Load $dev1 "./spi.elf"
+
+#set the clock cycle time [ns]
+# 1000000000ns/1000000MHz == 1000ns
+AvrDevice_SetClockFreq $dev1 1000
+
+#systemclock must know that this device will be stepped from application
+set sc [GetSystemClock]
+$sc Add $dev1
+
+# MNM
+set netB0      [new_Net]
+set netB1      [new_Net]
+set netB2      [new_Net]
+set netB3      [new_Net]
+
+[AvrDevice_GetPin $dev1 "B0"] SetOutState $Pin_PULLUP
+
+$netB0 Add [AvrDevice_GetPin $dev1 "B0"]
+$netB1 Add [AvrDevice_GetPin $dev1 "B1"]
+$netB2 Add [AvrDevice_GetPin $dev1 "B2"]
+$netB3 Add [AvrDevice_GetPin $dev1 "B3"]
+
+SpiSource spiSource "spidata" $netB0 $netB1 $netB2
+SpiSink spiSink $netB0 $netB1 $netB3
+set pinMonPinNameStr   "A0"
+set pinMonPinDescStr   "PORTA0"
+set pinMonPinHighStr   "NEGATE"
+set pinMonPinLowStr            "ASSERT"
+
+# This line did not work since the string "constants" are
+# apparently de-allocated after the constructor, and the
+# PinMonitor class keeps the pointers, not a copy to
+# the strings!
+#PinMonitor pinmon $dev1 "A0" "PORTA0" "NEGATE" "ASSERT"
+
+# This works because the variables do not get de-allocated.
+PinMonitor pinmon $dev1 $pinMonPinNameStr $pinMonPinDescStr $pinMonPinHighStr 
$pinMonPinLowStr
+
+set netF0      [new_Net]
+set netAref    [new_Net]
+
+$netF0 Add [AvrDevice_GetPin $dev1 "F0"]
+
+AdcPin adcPinSource "anadata" $netF0
+
+$netAref Add [AvrDevice_GetPin $dev1 "AREF"]
+
+set aRef [new_AdcAnalogPin]
+
+$aRef SetOutState $Pin_ANALOG
+
+$netAref Add $aRef
+
+$aRef setAnalogValue 5000000
+
+$sc Add spiSource
+$sc Add spiSink
+$sc Add adcPinSource
+
+GdbServer gdb1 $dev1 1212 0 0
+$sc Add gdb1
+
+# nice -n 19 xterm -e "avr-gdb $objfile -x gdbinit"
+
+#now run simulation
+$sc Endless
+exit
Index: examples/spi/main.cpp
===================================================================
RCS file: examples/spi/main.cpp
diff -N examples/spi/main.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ examples/spi/main.cpp       18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,107 @@
+/* 
+ * Demonstrate the use of the SpiSource, SpiSink, and PinMonitor.
+ *
+ * $Id$
+ */
+
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <avr/signal.h>
+#include <stdint.h>
+
+uint8_t                                txData;
+volatile uint8_t       rxData;
+
+static void startADC()
+{
+       ADCSRA  =       (       (1<<ADEN)       // ADC Enabled
+                               |       (1<<ADSC)       // Start Conversion NOW
+                               |       (0<<ADFR)       // Auto Trigger Disabled
+                               |       (1<<ADIF)       // Interrupt Flag 
Acknowledge
+                               |       (1<<ADIE)       // Interrupt enabled
+                               |       (0<<ADPS2)      // Prescaler should get 
between 50KHz-200KHz for max resolution
+                               |       (1<<ADPS1)      //   System Clock = 1MHz
+                               |       (1<<ADPS0)      //              
Prescaler = 1MHz/100KHz = ~10 thus = 8 : 1MHz/8 = 120KHz
+                               ) ;
+}
+
+static void    assertPA0(){
+       // asserted is LOW
+       PORTA   &= ~(1<<PA0);
+       }
+
+static void    negatePA0(){
+       // negated is HIG
+       PORTA   |= (1<<PA0);
+       }
+
+uint8_t        count;
+uint8_t        adcData;
+
+SIGNAL(SIG_ADC)
+{
+       adcData = ADCH;
+       startADC();
+}
+
+SIGNAL(SIG_SPI)
+{
+       rxData  = SPDR;
+       if(count % 2){
+               SPDR    = rxData;
+               }
+       else {
+               SPDR    = adcData;
+               }
+
+       if(count == 0){
+               assertPA0();
+               }
+
+       if(count == 128){
+               negatePA0();
+               }
+       ++count;
+}
+
+int main(int argc,char *argv[]){
+       ADMUX   =               (0<<REFS1)      // Use Vcc as ADC reference
+                               |       (1<<REFS0)      // Use Vcc as ADC 
reference
+                               |       (1<<ADLAR)      // Left justify result 
(percentage FS)
+                               |       (0<<MUX4)       // Always zero for our 
application
+                               |       (0<<MUX3)
+                               |       (0<<MUX2)
+                               |       (0<<MUX1)
+                               |       (0<<MUX0)
+                               ;
+
+       DDRB    &= ~(   (1<<PB0)        // /SS PortB pin 0 as input
+                               |       (1<<PB1)        // SCK PortB pin 1 as 
input for slave
+                               |       (1<<PB2)        // MOSI PortB pin 2 as 
input for slave
+                               );
+       DDRB    |=      (1<<PB3);               // MISO PortB pin 2 as output 
for slave
+       PORTA   |=      (1<<PA0);               // Negate "interrupt"
+       DDRA    |=  (1<<PA0);           // "Interrupt" output
+
+       SPCR    =               (1<<SPIE)       // interrupt enable
+                               |       (1<<SPE)        // SPI enable
+                               |       (0<<DORD)       // MSB first
+                               |       (0<<MSTR)       // Slave Mode
+                               |       (1<<CPOL)       // Clock HIGH when idle
+                               |       (0<<CPHA)       // Sample on leading 
edge
+                               |       (0<<SPR1)       // Slave has no affect
+                               |       (0<<SPR0)       // Slave has no affect
+                               ;
+
+       startADC();
+
+       sei();
+
+       for(;;);
+
+    return 0;
+}
+
+
+
+
Index: examples/spi/spidata
===================================================================
RCS file: examples/spi/spidata
diff -N examples/spi/spidata
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ examples/spi/spidata        18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,623 @@
+1 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+#
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+0 1 0
+0 0 0
+0 1 0
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 1
+0 0 1
+0 1 1
+0 1 0
+0 0 0
+0 1 0
+#
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
Index: src/Makefile.am
===================================================================
RCS file: /sources/simulavr/simulavrxx/src/Makefile.am,v
retrieving revision 1.31
diff -u -r1.31 Makefile.am
--- src/Makefile.am     16 Mar 2009 17:56:23 -0000      1.31
+++ src/Makefile.am     18 Mar 2009 20:37:42 -0000
@@ -27,15 +27,16 @@
 noinst_LTLIBRARIES=libsim.la
 
 libsim_la_SOURCES = \
-  application.cpp at4433.cpp at8515.cpp atmega128.cpp avrdevice.cpp \
-  avrerror.cpp avrfactory.cpp avrmalloc.cpp decoder.cpp decoder_trace.cpp \
-  flash.cpp gdbserver.cpp hardware.cpp helper.cpp hwacomp.cpp hwad.cpp \
-  hweeprom.cpp hwextirq.cpp hwmegaextirq.cpp hwmegatimer.cpp \
-  hwmegatimer0123irq.cpp hwport.cpp hwspi.cpp hwsreg.cpp hwstack.cpp \
-  hwtimer.cpp hwtimer01irq.cpp hwuart.cpp hwwado.cpp ioregs.cpp irqsystem.cpp \
-  keyboard.cpp lcd.cpp memory.cpp mysocket.cpp net.cpp pin.cpp pinatport.cpp \
-  printable.cpp rwmem.cpp scope.cpp serialrx.cpp serialtx.cpp systemclock.cpp \
-  trace.cpp ui.cpp
+  adcpin.cpp application.cpp at4433.cpp at8515.cpp atmega128.cpp \
+  avrdevice.cpp avrerror.cpp avrfactory.cpp avrmalloc.cpp decoder.cpp \
+  decoder_trace.cpp flash.cpp gdbserver.cpp hardware.cpp helper.cpp \
+  hwacomp.cpp hwad.cpp hweeprom.cpp hwextirq.cpp hwmegaextirq.cpp \
+  hwmegatimer.cpp hwmegatimer0123irq.cpp hwpinchange.cpp hwport.cpp hwspi.cpp \
+  hwsreg.cpp hwstack.cpp hwtimer.cpp hwtimer01irq.cpp hwuart.cpp \
+  hwwado.cpp ioregs.cpp irqsystem.cpp keyboard.cpp lcd.cpp memory.cpp \
+  mysocket.cpp net.cpp pin.cpp pinatport.cpp pinmon.cpp printable.cpp \
+  rwmem.cpp scope.cpp serialrx.cpp serialtx.cpp spisrc.cpp spisink.cpp \
+  systemclock.cpp trace.cpp ui.cpp 
 
 nodist_libsimulavr_la_SOURCES = $(TCL_WRAP_SRC)
 libsimulavr_la_LDFLAGS = -version-info 0:0:0 
@@ -43,18 +44,18 @@
   $(AVR_LIBBFD_LIB) $(AVR_LIBIBERTY_LIB) 
 
 pkginclude_HEADERS = \
-  application.h at4433.h at8515.h atmega128.h avrdevice.h \
+  adcpin.h application.h at4433.h at8515.h atmega128.h avrdevice.h \
   avrdevice_impl.h avrerror.h avrfactory.h avrmalloc.h breakpoint.h \
   config_deprecated.h decoder.h externaltype.h flash.h \
   funktor.h gdb.h global.h hardware.h helper.h hwacomp.h \
   hwad.h hweeprom.h hwextirq.h hwmegaextirq.h hwmegatimer.h \
-  hwmegatimer0123irq.h hwport.h hwspi.h hwsreg.h hwstack.h \
+  hwmegatimer0123irq.h hwpinchange.h hwport.h hwspi.h hwsreg.h hwstack.h \
   hwtimer.h hwtimer01irq.h hwuart.h hwwado.h ioregs.h \
   irqsystem.h keyboard.h keynumber_to_scancode.dat lcd.h \
-  memory.h mysocket.h net.h pin.h pinatport.h pinnotify.h \
-  printable.h rwmem.h scope.h serialrx.h serialtx.h \
-  simulationmember.h systemclock.h systemclocktypes.h trace.h \
-  types.h ui.h xcode_to_keynumber.dat
+  memory.h mysocket.h net.h pin.h pinatport.h pinnotify.h pinmon.h \
+  printable.h rwmem.h scope.h serialrx.h serialtx.h simulationmember.h \
+  spisrc.h spisink.h systemclock.h systemclocktypes.h trace.h types.h \
+  ui.h xcode_to_keynumber.dat
 
 simulavr_SOURCES = main.cpp $(COMMON_SRC)
 
Index: src/adcpin.cpp
===================================================================
RCS file: src/adcpin.cpp
diff -N src/adcpin.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/adcpin.cpp      18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,51 @@
+#include <iostream>
+#include "adcpin.h"
+
+AdcPin::AdcPin(        const char*             fileName,
+                               Net&                    pinNet
+                               ) throw():
+               _analogPin(),
+               _anaFile(fileName)
+               {
+               _analogPin.SetOutState(Pin::ANALOG);
+               pinNet.Add(&_analogPin);
+
+               if(!_anaFile){
+                       cerr << "Cannot open Analog input file \"" << fileName 
<< "\"." << endl;
+                       exit(1);
+                       }
+       }
+
+char*  readNextLine(std::ifstream& f,char* buffer,unsigned 
len,SystemClockOffset *timeToNextStepIn_ns){
+       for(unsigned i=0;i<2;++i){
+               while(f.getline(buffer, len)){
+                       // Skip comment lines
+                       if(buffer[0] == '#') continue;
+                       return buffer;
+                       }
+               f.clear();
+               f.seekg (0, ios::beg);
+               }
+       return 0;
+       }
+
+int    AdcPin::Step(bool &trueHwStep, SystemClockOffset *timeToNextStepIn_ns){
+       if(!_anaFile) return 0;
+
+       char    lineBuffer[1024];
+
+       
if(!readNextLine(_anaFile,lineBuffer,sizeof(lineBuffer),timeToNextStepIn_ns)){
+               _anaFile.close();
+               }
+
+       char*   p       = lineBuffer;
+       unsigned long   delayInNs               = strtoul(p, &p, 0);
+       int     analogValue             = (int)strtol(p, &p, 0);
+
+       _analogPin.setAnalogValue(analogValue);
+
+       *timeToNextStepIn_ns    = delayInNs;
+
+       return 0;
+       }
+
Index: src/adcpin.h
===================================================================
RCS file: src/adcpin.h
diff -N src/adcpin.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/adcpin.h        18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,40 @@
+#ifndef _adcpinh_
+#define _adcpinh_
+#include <fstream>
+#include "avrdevice.h"
+
+// This class allows the analog simulator access
+// to the analogValue field of the pin and causes
+// the Net to update (CalcNet). Note there is
+// no dependency on the UserInterface class.
+class AdcAnalogPin : public Pin {
+       public:
+               // Set the analog value and propagte through Net.
+               inline void     setAnalogValue(int value) throw(){
+                       analogValue     = value;
+               connectedTo->CalcNet();
+                       }
+       };
+
+// The purpose of this class is to stimulate a pin
+// with an analog pattern specified by a file.
+// The file will contain an "analog sample value" on
+// each line, along with a duration in nano-seconds
+// that must elapse before the value is changed.
+class AdcPin : public SimulationMember {
+       private:
+               AdcAnalogPin            _analogPin;     // Output to AVR
+
+               // The analog input file.
+               std::ifstream           _anaFile;
+
+       public:
+               AdcPin( const char*             fileName,
+                               Net&                    pinNet
+                               ) throw();
+
+       private:        // SimulationMember
+        int    Step(bool &trueHwStep, SystemClockOffset 
*timeToNextStepIn_ns=0);
+       };
+
+#endif
Index: src/hwpinchange.cpp
===================================================================
RCS file: src/hwpinchange.cpp
diff -N src/hwpinchange.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/hwpinchange.cpp 18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,273 @@
+#include <iostream>
+#include "hwpinchange.h"
+#include "irqsystem.h"
+#include "trace.h"
+
+HWPcir::HWPcir(        AvrDevice*              avr,
+                               HWIrqSystem&    irqSystem,
+                               unsigned                vector0,
+                               unsigned                vector1,
+                               unsigned                vector2,
+                               unsigned                vector3,
+                               unsigned                vector4,
+                               unsigned                vector5,
+                               unsigned                vector6,
+                               unsigned                vector7
+                               ) throw():
+               Hardware(avr),
+               _pcifr(0),
+               _pcicr(0),
+               _irqSystem(irqSystem),
+               _vector0(vector0),
+               _vector1(vector1),
+               _vector2(vector2),
+               _vector3(vector3),
+               _vector4(vector4),
+               _vector5(vector5),
+               _vector6(vector6),
+               _vector7(vector7)
+               {
+       }
+
+bool   HWPcir::getPcifr(unsigned pcifrBit) throw(){
+       return _pcifr & (1<<pcifrBit);
+       }
+
+unsigned       HWPcir::convertBitToVector(unsigned bit) const throw(){
+       unsigned vector = ~0;
+       switch(bit){
+               case 0:
+                       vector  = _vector0;
+                       break;
+               case 1:
+                       vector  = _vector1;
+                       break;
+               case 2:
+                       vector  = _vector2;
+                       break;
+               case 3:
+                       vector  = _vector3;
+                       break;
+               case 4:
+                       vector  = _vector4;
+                       break;
+               case 5:
+                       vector  = _vector5;
+                       break;
+               case 6:
+                       vector  = _vector6;
+                       break;
+               case 7:
+                       vector  = _vector7;
+                       break;
+               default:
+                       cerr << "HWPcir: invalid PCIFR bit specified.." << endl;
+                       break;
+               };
+       return vector;
+       }
+
+void   HWPcir::setPcifr(unsigned pcifrBit) throw(){
+       if(_pcifr & (1<<pcifrBit)){
+               // Already set/pending
+               return;
+               }
+       // At this point we have a *new* pin-change interrupt.
+       _pcifr  |= (1<<pcifrBit);
+
+       unsigned vector = convertBitToVector(pcifrBit);
+
+       if(vector == (unsigned)~0){
+               cerr << "HWPcir: Attempt to set invalid pin-change interrupt." 
<< endl;
+               return;
+               }
+
+       if(_pcicr & (1<<pcifrBit)){
+               _irqSystem.SetIrqFlag(this,vector);
+               }
+       }
+
+void   HWPcir::setPcifrMask(unsigned char val) throw(){
+       // Only XOR bits that are set/pending
+       val             &= _pcifr;
+
+       // Clear the appropriate pending interrupts
+       _pcifr ^= val;
+
+       for(unsigned i=0;i<8;++i){
+               if(val & (1<<i)){
+                       // We're trying to clear an interrupt
+                       // An interrupt is pending
+                       if(_pcicr & (1<<i)){
+                               // The interrupt is enabled and pending,
+                               // so tell the interrupt system
+                               unsigned vector = convertBitToVector(i);
+                               _irqSystem.ClearIrqFlag(vector);
+                               }
+                       }
+               }
+
+       // Clear the bits in the register
+       _pcifr ^= val;
+       }
+
+unsigned char  HWPcir::getPcifrMask() const throw(){
+       return _pcifr;
+       }
+
+void   HWPcir::setPcicrMask(unsigned char val) throw(){
+       unsigned char   pcicrChanges    = _pcicr ^ val;
+       for(unsigned i=0;i<8;++i){
+               if(pcicrChanges & (1<<i)){
+                       // Bit changed
+                       if(val & (1<<i)){
+                               //  Bit is being enabled
+                               if(_pcifr & (1<<i)){
+                                       // Change interrupt pending
+                                       unsigned vector = convertBitToVector(i);
+                                       _irqSystem.SetIrqFlag(this,vector);
+                                       }
+                               }
+                       else {
+                               // Bit is being disabled
+                               if(val & (1<<i)){
+                                       // Change interrupt pending
+                                       unsigned vector = convertBitToVector(i);
+                                       _irqSystem.ClearIrqFlag(vector);
+                                       }
+                               }
+                       }
+               }
+       _pcicr  = val;
+       }
+
+unsigned char  HWPcir::getPcicrMask() const throw(){
+       return _pcicr;
+       }
+
+               
+void HWPcir::Reset(){
+       _pcicr  = 0;
+       _pcifr  = 0;
+       }
+
+void HWPcir::ClearIrqFlag(unsigned int vector){
+       if(vector == _vector0){
+               _pcifr  &= ~(1<<0);
+        _irqSystem.ClearIrqFlag(vector);
+               return;
+               }
+       if(vector == _vector1){
+               _pcifr  &= ~(1<<1);
+        _irqSystem.ClearIrqFlag(vector);
+               return;
+               }
+       if(vector == _vector2){
+               _pcifr  &= ~(1<<2);
+        _irqSystem.ClearIrqFlag(vector);
+               return;
+               }
+       if(vector == _vector3){
+               _pcifr  &= ~(1<<3);
+        _irqSystem.ClearIrqFlag(vector);
+               return;
+               }
+       if(vector == _vector4){
+               _pcifr  &= ~(1<<4);
+        _irqSystem.ClearIrqFlag(vector);
+               return;
+               }
+       if(vector == _vector5){
+               _pcifr  &= ~(1<<5);
+        _irqSystem.ClearIrqFlag(vector);
+               return;
+               }
+       if(vector == _vector6){
+               _pcifr  &= ~(1<<6);
+        _irqSystem.ClearIrqFlag(vector);
+               return;
+               }
+       if(vector == _vector7){
+               _pcifr  &= ~(1<<7);
+        _irqSystem.ClearIrqFlag(vector);
+               return;
+               }
+        cerr << "HWPcir: Attempt to clear non-existent irq vector";
+       }
+
+HWPcmsk::HWPcmsk(      HWPcifrApi&     pcifrApi,
+                                       unsigned        pcifrBit
+                                       ) throw():
+               _pcifrApi(pcifrApi),
+               _pcmsk(0),
+               _pcifrBit(pcifrBit)
+               {
+       }
+
+void   HWPcmsk::setPcmskMask(unsigned char val) throw(){
+       _pcmsk  = val;
+       }
+
+unsigned char  HWPcmsk::getPcmskMask() const throw(){
+       return _pcmsk;
+       }
+
+void   HWPcmsk::pinChanged(unsigned bit) throw(){
+       if(_pcmsk & (1<<bit)){
+               _pcifrApi.setPcifr(_pcifrBit);
+               }
+       }
+
+PinChange::PinChange(  Pin&                            pin,
+                                               HWPcmskPinApi&          
pcmskPinApi,
+                                               unsigned                        
pcmskBit
+                                               ) throw():
+               _pin(pin),
+               _pcmskPinApi(pcmskPinApi),
+               _pcmskBit(pcmskBit),
+               _prevState(true)
+               {
+       pin.RegisterCallback(this);
+       }
+
+void PinChange::PinStateHasChanged(Pin* pin){
+       bool    currentState    = (bool)*pin;
+       if(currentState == _prevState){
+               return;
+               }
+
+       _prevState      = currentState;
+
+       _pcmskPinApi.pinChanged(_pcmskBit);
+       }
+
+unsigned char RWPcicr::operator=(unsigned char val){
+       if (core->trace_on) trioaccess("PCICR",val);
+       _pcirMaskApi.setPcicrMask(val);
+       return val;
+       }
+
+RWPcicr::operator unsigned char() const{
+       return _pcirMaskApi.getPcicrMask();
+       }
+
+unsigned char RWPcifr::operator=(unsigned char val){
+       if (core->trace_on) trioaccess("PCIFR",val);
+       _pcirMaskApi.setPcifrMask(val);
+       return val;
+       }
+
+RWPcifr::operator unsigned char() const{
+       return _pcirMaskApi.getPcifrMask();
+       }
+
+unsigned char RWPcmsk::operator=(unsigned char val){
+       if (core->trace_on) trioaccess("PCMSK",val);
+       _pcmskApi.setPcmskMask(val);
+       return val;
+       }
+
+RWPcmsk::operator unsigned char() const{
+       return _pcmskApi.getPcmskMask();
+       }
+
Index: src/hwpinchange.h
===================================================================
RCS file: src/hwpinchange.h
diff -N src/hwpinchange.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/hwpinchange.h   18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,174 @@
+#ifndef _hwpinchangeh_
+#define _hwpinchangeh_
+#include "avrdevice.h"
+#include "pin.h"
+#include "pinnotify.h"
+#include "net.h"
+#include "rwmem.h"
+#include "hardware.h"
+
+class HWPcifrApi {
+       public:
+               virtual ~HWPcifrApi(){}
+               virtual bool    getPcifr(unsigned bit) throw()=0;
+               virtual void    setPcifr(unsigned bit) throw()=0;
+
+       };
+
+class HWPcicrApi {
+       public:
+               virtual ~HWPcicrApi(){}
+               virtual bool    getPcicr(unsigned bit) throw()=0;
+               virtual void    setPcicr(unsigned bit) throw()=0;
+
+       };
+
+class HWPcmskApi {
+       public:
+               virtual ~HWPcmskApi(){}
+               virtual void                    setPcmskMask(unsigned char val) 
throw()=0;
+               virtual unsigned char   getPcmskMask() const throw()=0;
+
+//             virtual bool    getPcmsk(unsigned bit) throw()=0;
+//             virtual void    setPcmsk(unsigned bit) throw()=0;
+
+       };
+
+class HWPcmskPinApi {
+       public:
+               virtual ~HWPcmskPinApi(){}
+               virtual void    pinChanged(unsigned bit) throw()=0;
+       };
+
+class HWPcirMaskApi {
+       public: // HWPcirMaskApi
+               virtual void                    setPcifrMask(unsigned char val) 
throw()=0;
+               virtual unsigned char   getPcifrMask() const throw()=0;
+
+               virtual void                    setPcicrMask(unsigned char val) 
throw()=0;
+               virtual unsigned char   getPcicrMask() const throw()=0;
+       };
+               
+class HWPcir : public HWPcifrApi , public HWPcirMaskApi , public Hardware {
+       private:
+               unsigned char   _pcifr;
+               unsigned char   _pcicr;
+               HWIrqSystem&    _irqSystem;
+
+               const unsigned  _vector0;
+               const unsigned  _vector1;
+               const unsigned  _vector2;
+               const unsigned  _vector3;
+               const unsigned  _vector4;
+               const unsigned  _vector5;
+               const unsigned  _vector6;
+               const unsigned  _vector7;
+
+       public:
+               // Unimplemented vectors are set
+               // to a value of all ones (i.e. ~0).
+               HWPcir( AvrDevice*              avr,
+                               HWIrqSystem&    irqSystem,
+                               unsigned                vector0 = ~0,
+                               unsigned                vector1 = ~0,
+                               unsigned                vector2 = ~0,
+                               unsigned                vector3 = ~0,
+                               unsigned                vector4 = ~0,
+                               unsigned                vector5 = ~0,
+                               unsigned                vector6 = ~0,
+                               unsigned                vector7 = ~0
+                               ) throw();
+
+       private:
+               unsigned        convertBitToVector(unsigned bit) const throw();
+
+       public: // HWPcifrApi
+               bool                    getPcifr(unsigned pcifrBit) throw();
+               void                    setPcifr(unsigned pcifrBit) throw();
+
+       public: // HWPcirMaskApi
+               void                    setPcifrMask(unsigned char val) throw();
+               unsigned char   getPcifrMask() const throw();
+
+               void                    setPcicrMask(unsigned char val) throw();
+               unsigned char   getPcicrMask() const throw();
+               
+       private:        // Hardware
+        void Reset();
+        void ClearIrqFlag(unsigned int vector);
+
+       
+       };
+
+class HWPcmsk : public HWPcmskApi , public HWPcmskPinApi {
+       private:
+               HWPcifrApi&                     _pcifrApi;
+               unsigned char           _pcmsk;
+               const unsigned          _pcifrBit;
+
+       public:
+               // constructor
+               HWPcmsk(        HWPcifrApi&     pcifrApi,
+                                       unsigned        pcifrBit
+                                       ) throw();
+
+       public: // HWPcmskApi
+               void                    setPcmskMask(unsigned char val) throw();
+               unsigned char   getPcmskMask() const throw();
+
+       public: // HWPcmskPinApi
+               void                    pinChanged(unsigned bit) throw();
+       };
+
+// This class monitors a single pin for changes
+// an reports an interrupt if the pin chages.
+class PinChange : public HasPinNotifyFunction {
+       private:
+               Pin&                            _pin;
+               HWPcmskPinApi&          _pcmskPinApi;
+               const unsigned          _pcmskBit;
+
+               // Previous state of pin since change callback doesn't *really*
+               // mean "change"!
+               bool                            _prevState;
+
+       public:
+               PinChange(      Pin&                    pin,
+                                       HWPcmskPinApi&  pcmskPinApi,
+                                       unsigned                pcmskBit
+                                       ) throw();
+
+       private:        // HasPinNotifyFunction
+        void PinStateHasChanged(Pin*);
+       };
+
+class RWPcicr : public RWMemoryMembers {
+       private:
+               HWPcirMaskApi&  _pcirMaskApi;
+       public:
+               RWPcicr(AvrDevice *c,  HWPcirMaskApi& pcirMaskApi): 
RWMemoryMembers(c), _pcirMaskApi(pcirMaskApi) {}
+               virtual unsigned char operator=(unsigned char);
+               virtual operator unsigned char() const;
+       };
+
+class RWPcifr : public RWMemoryMembers {
+       private:
+               HWPcirMaskApi&  _pcirMaskApi;
+
+       public:
+               RWPcifr(AvrDevice *c, HWPcirMaskApi& pcirMaskApi ): 
RWMemoryMembers(c), _pcirMaskApi(pcirMaskApi) {}
+               virtual unsigned char operator=(unsigned char);
+               virtual operator unsigned char() const;
+       };
+
+class RWPcmsk : public RWMemoryMembers {
+       private:
+               HWPcmskApi&     _pcmskApi;
+
+       public:
+               RWPcmsk(AvrDevice *c, HWPcmskApi& pcmskApi ): 
RWMemoryMembers(c), _pcmskApi(pcmskApi) {}
+               virtual unsigned char operator=(unsigned char);
+               virtual operator unsigned char() const;
+       };
+
+#endif
Index: src/main.cpp
===================================================================
RCS file: /sources/simulavr/simulavrxx/src/main.cpp,v
retrieving revision 1.23
diff -u -r1.23 main.cpp
--- src/main.cpp        13 Mar 2009 20:43:34 -0000      1.23
+++ src/main.cpp        18 Mar 2009 20:37:42 -0000
@@ -94,6 +94,10 @@
    string tracefilename("unknown");
    int global_gdbserver_port    = 1212;
    int global_gdb_debug         = 0;
+   bool use_spi_source=false;
+   bool use_spi_sink=false;
+   const char* pinmon = 0;
+
    bool globalWaitForGdbConnection=true; //please wait for gdb connection
    int userinterface_flag=0;
    unsigned long long fcpu=4000000;
Index: src/pinmon.cpp
===================================================================
RCS file: src/pinmon.cpp
diff -N src/pinmon.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/pinmon.cpp      18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,35 @@
+#include <iostream>
+#include "pinmon.h"
+
+PinMonitor::PinMonitor(        AvrDevice&      avr,
+                                               const char*     pinNameStr, // 
AVR pin name.  (e.g. "B1","C2", etc.)
+                                               const char*     pinDescStr,
+                                               const char*     pinHighStr,
+                                               const char*     pinLowStr
+                                               ) throw():
+               _prevState(true)
+               {
+       Pin*    pin     = avr.GetPin(pinNameStr);
+       pin->RegisterCallback(this);
+       _pinDescStr     = pinDescStr?pinDescStr:pinNameStr;
+       _pinHighStr     = pinHighStr?pinHighStr:"HIGH";
+       _pinLowStr      = pinLowStr?pinLowStr:"LOW";
+       }
+
+void PinMonitor::PinStateHasChanged(Pin* pin){
+       const char*     stateStr;
+       if((bool)*pin == _prevState){
+               return;
+               }
+       if((bool)*pin){
+               stateStr        = _pinHighStr;
+               _prevState      = true;
+               }
+       else {
+               stateStr        = _pinLowStr;
+               _prevState      = false;
+               }
+
+       cout << _pinDescStr << ": " << stateStr << endl;
+       }
+
Index: src/pinmon.h
===================================================================
RCS file: src/pinmon.h
diff -N src/pinmon.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/pinmon.h        18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,32 @@
+#ifndef _pinmonh_
+#define _pinmonh_
+#include "avrdevice.h"
+#include "pin.h"
+#include "pinnotify.h"
+#include "net.h"
+
+// This class monitors a single pin and prints
+// changes in the pin state to stdout.
+class PinMonitor : public HasPinNotifyFunction {
+       private:
+               // This string printed as a prefix on stdout with each pin 
change.
+               const char*     _pinDescStr;
+               // String printed when the pin is HIGH.
+               const char*     _pinHighStr;
+               // String printed when the pin is LOW.
+               const char*     _pinLowStr;
+               // Previous state of pin since change callback doesn't *really*
+               // mean "change"!
+               bool            _prevState;
+       public:
+               PinMonitor(     AvrDevice&      avr,
+                                       const char*     pinNameStr, // AVR pin 
name.  (e.g. "B1","C2", etc.)
+                                       const char*     pinDescStr      = 0,
+                                       const char*     pinHighStr      = 0,
+                                       const char*     pinLowStr       = 0
+                                       ) throw();
+       private:        // HasPinNotifyFunction
+        void PinStateHasChanged(Pin*);
+       };
+
+#endif
Index: src/simulavr.i
===================================================================
RCS file: /sources/simulavr/simulavrxx/src/simulavr.i,v
retrieving revision 1.8
diff -u -r1.8 simulavr.i
--- src/simulavr.i      16 Mar 2009 17:56:23 -0000      1.8
+++ src/simulavr.i      18 Mar 2009 20:37:42 -0000
@@ -17,6 +17,10 @@
 #include "lcd.h"
 #include "serialrx.h"
 #include "serialtx.h"
+#include "spisrc.h"
+#include "spisink.h"
+#include "adcpin.h"
+#include "pinmon.h"
 #include "scope.h"
 
 SystemClock &GetSystemClock() { return SystemClock::Instance(); }
@@ -41,6 +45,10 @@
 %include "lcd.h"
 %include "serialrx.h"
 %include "serialtx.h"
+%include "spisrc.h"
+%include "spisink.h"
+%include "adcpin.h"
+%include "pinmon.h"
 %include "scope.h"
 
 
Index: src/spisink.cpp
===================================================================
RCS file: src/spisink.cpp
diff -N src/spisink.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/spisink.cpp     18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,127 @@
+#include <iostream>
+#include "spisink.h"
+
+SpiSink::SpiSink(      Net&            ssNet,
+                                       Net&            sclkNet,
+                                       Net&            misoNet,
+                                       bool            clockIsIdleHigh,
+                                       bool            clockSampleOnLeadingEdge
+                                       ) throw():
+               _ss(),
+               _sclk(),
+               _miso(),
+               _state(0),
+               _sr(0),
+               _clockIsIdleHigh(clockIsIdleHigh),
+               _clockSampleOnLeadingEdge(clockSampleOnLeadingEdge),
+               _prevClkState(clockIsIdleHigh),
+               _prevSS(true)
+               {
+               _ss.SetOutState(Pin::PULLUP);
+               ssNet.Add(&_ss);
+
+               _sclk.SetOutState(Pin::PULLUP);
+               sclkNet.Add(&_sclk);
+
+               _miso.SetOutState(Pin::PULLUP);
+               misoNet.Add(&_miso);
+       }
+
+int    SpiSink::Step(bool &trueHwStep, SystemClockOffset *timeToNextStepIn_ns){
+       *timeToNextStepIn_ns    = 1000; // Once every microsecond
+       bool    sample = false;
+
+       if(!_ss){
+               if(_prevClkState != (bool)_sclk){
+                       _prevClkState   = (bool)_sclk;
+                       if(_clockIsIdleHigh){
+                               // Clock is HIGH when idle
+                               if(_clockSampleOnLeadingEdge){
+                                       // Sample on leading edge
+                                       sample  = ((bool)_sclk)?false:true;
+                                       }
+                               else {
+                                       // Sample on trailing edge
+                                       sample  = ((bool)_sclk)?true:false;
+                                       }
+                               }
+                       else {
+                               // Clock is LOW when idle
+                               if(_clockSampleOnLeadingEdge){
+                                       // Sample on leading edge
+                                       sample  = ((bool)_sclk)?true:false;
+                                       }
+                               else {
+                                       // Sample on trailing edge
+                                       sample  = ((bool)_sclk)?false:true;
+                                       }
+                               }
+                       }
+               }
+       else {
+               _sr             = 0;
+               _state  = 0;
+               }
+
+       for(;;){
+               switch(_state){
+                       case 0: // Waiting for /SS
+                               if(!_ss){
+                                       _state  = 1;
+                                       continue;
+                                       }
+                               break;
+                       case 1: // First sample
+                       case 2: // Second sample
+                       case 3: // Third sample
+                       case 4: // Fourth sample
+                       case 5: // Fifth sample
+                       case 6: // Sixth sample
+                       case 7: // Seventh sample
+                               if(sample){
+                                       _sr     <<= 1;
+                                       if(_miso){
+                                               _sr     |= 0x01;
+                                               }
+                                       ++_state;
+                                       }
+                               break;
+                       case 8: // First sample
+                               if(sample){
+                                       _sr     <<= 1;
+                                       if(_miso){
+                                               _sr     |= 0x01;
+                                               }
+                                       _state  = 1;
+
+                                       streamsize      streamWidth = 
cout.width();
+                                       ios_base::fmtflags      saved   = 
cout.flags();
+                                       
cout.setf(ios_base::hex,ios_base::basefield);
+                                       cout.setf(ios_base::uppercase);
+                                       cout.setf(ios_base::right);
+                                       cout << "spisink: 0x";
+                                       cout.width(2);
+                                       cout.fill('0');
+                                       cout << (unsigned long)_sr;
+                                       cout << endl;
+                                       cout.width(streamWidth);
+                                       cout.flags(saved);
+                                       }
+                               break;
+                       }
+               break;
+               }
+
+       if((bool)_ss != _prevSS){
+               if(_ss){
+                       cout << "spisink: /SS negated" << endl;
+                       }
+               else {
+                       cout << "spisink: /SS asserted" << endl;
+                       }
+               _prevSS = _ss;
+               }
+
+       return 0;
+       }
+
Index: src/spisink.h
===================================================================
RCS file: src/spisink.h
diff -N src/spisink.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/spisink.h       18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,29 @@
+#ifndef _spisinkh_
+#define _spisinkh_
+#include "avrdevice.h"
+
+// This class monitors the /SS, SCLK, and MISO pin of the AVR and
+// prints the results one byte at a time to stdout.
+class SpiSink : public SimulationMember {
+       private:
+               Pin                             _ss;    // Output to AVR
+               Pin                             _sclk;  // Output to AVR
+               Pin                             _miso;  // Output to AVR
+               unsigned                _state;
+               unsigned char   _sr;
+               bool                    _clockIsIdleHigh;
+               bool                    _clockSampleOnLeadingEdge;
+               bool                    _prevClkState;
+               bool                    _prevSS;
+       public:
+               SpiSink(        Net&            ssNet,
+                                       Net&            sclkNet,
+                                       Net&            misoNet,
+                                       bool            clockIsIdleHigh = true,
+                                       bool            
clockSampleOnLeadingEdge = true
+                                       ) throw();
+       private:        // SimulationMember
+        int    Step(bool &trueHwStep, SystemClockOffset 
*timeToNextStepIn_ns=0);
+       };
+
+#endif
Index: src/spisrc.cpp
===================================================================
RCS file: src/spisrc.cpp
diff -N src/spisrc.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/spisrc.cpp      18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,63 @@
+#include <iostream>
+#include "spisrc.h"
+
+SpiSource::SpiSource(  const char*     fileName,
+                                               Net&            ssNet,
+                                               Net&            sclkNet,
+                                               Net&            mosiNet
+                                               ) throw():
+               _ss(),
+               _sclk(),
+               _mosi(),
+               _spiFile(fileName)
+               {
+               _ss.SetOutState(Pin::HIGH);
+               ssNet.Add(&_ss);
+
+               _sclk.SetOutState(Pin::HIGH);
+               sclkNet.Add(&_sclk);
+
+               _mosi.SetOutState(Pin::HIGH);
+               mosiNet.Add(&_mosi);
+
+               if(!_spiFile){
+                       cerr << "Cannot open SPI Source input file " << 
fileName << endl;
+                       exit(1);
+                       }
+       }
+
+static char*   readNextLine(std::ifstream& f,char* buffer,unsigned 
len,SystemClockOffset *timeToNextStepIn_ns){
+       *timeToNextStepIn_ns    = 100000;       // Once every 100 microseconds
+       for(unsigned i=0;i<2;++i){
+               while(f.getline(buffer, len)){
+                       if(buffer[0] == '#') continue;
+                       return buffer;
+                       }
+               *timeToNextStepIn_ns    = 1000000;      // Once every 100 
microseconds
+               f.clear();
+               f.seekg (0, ios::beg);
+               }
+       return 0;
+       }
+
+int    SpiSource::Step(bool &trueHwStep, SystemClockOffset 
*timeToNextStepIn_ns){
+       if(!_spiFile) return 0;
+
+       char    lineBuffer[1024];
+
+       
if(!readNextLine(_spiFile,lineBuffer,sizeof(lineBuffer),timeToNextStepIn_ns)){
+               _spiFile.close();
+               return 0;
+               }
+
+       char*   p       = lineBuffer;
+       unsigned long   ss              = strtoul(p, &p, 0);
+       unsigned long   sclk    = strtoul(p, &p, 0);
+       unsigned long   output  = strtoul(p, &p, 0);
+
+       _ss     = (ss)?'H':'L';
+       _sclk   = (sclk)?'H':'L';
+       _mosi   = (output)?'H':'L';
+       return 0;
+       }
+
Index: src/spisrc.h
===================================================================
RCS file: src/spisrc.h
diff -N src/spisrc.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/spisrc.h        18 Mar 2009 20:37:42 -0000
@@ -0,0 +1,23 @@
+#ifndef _spisrch_
+#define _spisrch_
+#include <fstream>
+#include "avrdevice.h"
+
+class SpiSource : public SimulationMember {
+       private:
+               Pin                             _ss;    // Output to AVR
+               Pin                             _sclk;  // Output to AVR
+               Pin                             _mosi;  // Output to AVR
+               std::ifstream   _spiFile;
+       public:
+               SpiSource(      const char*     fileName,
+                                       Net&            ssNet,
+                                       Net&            sclkNet,
+                                       Net&            mosiNet
+                                       ) throw();
+       private:        // SimulationMember
+        int    Step(bool &trueHwStep, SystemClockOffset 
*timeToNextStepIn_ns=0);
+       };
+
+
+#endif

reply via email to

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