diff --git a/linear_pendulum_2009/avr/pccom.c b/linear_pendulum_2009/avr/pccom.c
new file mode 100644
index 0000000000000000000000000000000000000000..861698bdbde6829a66a76e32b7a2281fef544d9c
--- /dev/null
+++ b/linear_pendulum_2009/avr/pccom.c
@@ -0,0 +1,188 @@
+// pccom.c: Communication interface to PC via serialio_core.
+
+#include "pccom.h"
+#include "serialio_core.h"
+#include "vel_control.h"
+
+/*
+ * Serial I/O assignments
+ *
+ *   AO 0 -- Axis 1  motor voltage
+ *   A0 1 -- Axis 1  velocity reference !
+ *
+ *   EI 0 -- Axis 1  position !
+ *   EI 1 -- Axis 1  filtered velocity !
+ *   EI 5 -- Axis 1  position with predicted fraction
+ *   EI 6 -- Axis 1  position unquantized
+ *
+ *   AI 2 -- Axis 1  current
+ *   AI 3 -- Pendulum angle !
+ *
+ *   AI 4 -- Axis 1  motor voltage (actual)
+ *
+ *   DI 0 -- Axis 1  endpoint sensor
+ */
+
+#define POLL_AXIS1_POSITION      0x0001
+#define POLL_AXIS1_VELOCITY      0x0002
+//#define POLL_PEND_ANGLE          0x0004
+//#define POLL_AXIS1_RESET         0x0008
+#define POLL_CONFIG              0x8000
+
+static volatile uint16_t pccom_poll=0;
+
+
+// ---------------------------------- Receiver --------------------------------
+
+// only call from UART receive interrupt
+static inline void addPoll(uint16_t flags) {
+  pccom_poll |= flags;
+}
+
+
+void pccom_receiveByte(char ch)
+{
+  switch (serialio_RXC(ch)) {
+  case serialio_clearbit: {
+    switch (serialio_channel) {
+    }
+  } break;
+  case serialio_setbit: {
+    switch (serialio_channel) {
+    }
+  } break;
+  case serialio_pollbit: {
+    switch (serialio_channel) {
+      //case 0: { addPoll(POLL_AXIS1_RESET); } break;
+    }
+  } break;
+  case serialio_pollchannel: {
+    switch (serialio_channel) {
+    case 0:  { addPoll(POLL_AXIS1_POSITION); } break;
+    case 1:  { addPoll(POLL_AXIS1_VELOCITY); } break;
+      //case 2:  { addPoll(POLL_PEND_ANGLE); } break;
+    case 31: { addPoll(POLL_CONFIG); } break;
+    }
+  } break;
+  case serialio_setchannel: {
+    switch (serialio_channel) {
+    case 0: { 
+      setRef(serialio_value - (1L<<12));
+    } break;
+    }
+  } break;
+  case serialio_more: {
+  } break;
+    
+  case serialio_error: {
+  } break;
+  }
+}
+
+
+// ----------------------------------- Sender ------------------------------
+// return true if more to send
+static uint8_t sendConfigPacket(uint8_t position)
+{
+  switch (position) {
+    case 0: CONF_ANALOG_IN(0, CONF_RESOLUTION(16)); break;     // Position (now reference)
+    case 1: CONF_ANALOG_IN(0, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
+    case 2: CONF_ANALOG_IN(0, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
+
+      case 3: CONF_ANALOG_IN(1, CONF_RESOLUTION(18)); break;     // Velocity estimate
+      case 4: CONF_ANALOG_IN(1, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
+      case 5: CONF_ANALOG_IN(1, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
+ 
+     case 6: CONF_ANALOG_OUT(0, CONF_RESOLUTION(13)); break;    // Reference to vel-ctrl
+     case 7: CONF_ANALOG_OUT(0, CONF_MIN(CONF_NEGATIVE_VOLT(1))); break;
+     case 8: CONF_ANALOG_OUT(0, CONF_MAX(CONF_POSITIVE_VOLT(1))); break;
+      
+    default: CONF_END(); return 0;
+  }
+  
+  return 1;
+}
+
+static uint8_t sendNextPacket() // returns 1 if a packet was available
+{
+  static int8_t configPosition = -1;
+
+//  static uint16_t toPoll = 0;
+//  // see if we should fetch new poll mask
+//  if (toPoll == 0) {
+//    toPoll = pccom_poll; 
+//    pccom_poll = 0;
+//    if (toPoll == 0) return 0;    
+//  }
+#define toPoll pccom_poll // OK since sender and receiver are mutexed
+
+  // Send _first_ requested item (only one packet!)
+  if (toPoll & POLL_AXIS1_POSITION) { 
+    toPoll &= ~POLL_AXIS1_POSITION;
+    serialio_putchannel(0, getPosition()+(1L<<15)); 
+  }
+  else if (toPoll & POLL_AXIS1_VELOCITY) { 
+    toPoll &= ~POLL_AXIS1_VELOCITY;
+    serialio_putchannel(1, getVelocity()+(1L<<17)); 
+  }
+  else if (toPoll & POLL_CONFIG) {
+    if (configPosition < 0) configPosition = 0; // Start sending config?   
+    if (!sendConfigPacket(configPosition)) {    // Last packet?
+      configPosition = -1;
+      toPoll &= ~POLL_CONFIG;
+    }
+    else configPosition++;                      // Advance to next packet
+  }
+  else return 0; // should never happen!
+
+  return 1;
+}
+
+// ---- Send buffering ----
+
+#define PCCOM_SEND_BUFFER_SIZE 6 // just enough for one serialio_putchannel() packet
+
+uint8_t pccom_sendBuffer[PCCOM_SEND_BUFFER_SIZE]; // Updated by serialio_putchar()
+uint8_t pccom_sendBufferPosition = 0;             // Updated by pccom_getNextByteToSend()
+uint8_t pccom_sendBufferUsed = 0;                 // Updated by serialio_putchar(),
+                                                  // and pccom_getNextByteToSend() when
+                                                  // the buffer is empty.
+
+void serialio_putchar(unsigned char ch) {
+  if (pccom_sendBufferUsed < PCCOM_SEND_BUFFER_SIZE) {
+    pccom_sendBuffer[pccom_sendBufferUsed] = ch;
+    pccom_sendBufferUsed++;
+  }
+  else {
+    // Buffer already full -- must never happen!
+    // main_emergencyStop(); // show that something is wrong
+  }
+}
+
+int16_t pccom_getNextByteToSend()
+{
+  if (pccom_sendBufferPosition >= pccom_sendBufferUsed) {
+    // Try to refill buffer
+    pccom_sendBufferPosition = 0;
+    pccom_sendBufferUsed = 0;
+
+    //if (!sendNextPacket()) return -1;
+    sendNextPacket();
+  }
+  
+  if (pccom_sendBufferPosition >= pccom_sendBufferUsed) return -1; // no data
+  else {
+    // Return next byte
+    uint8_t data = pccom_sendBuffer[pccom_sendBufferPosition];
+    pccom_sendBufferPosition++;
+    return data;
+  }  
+}
+
+
+// ------------------------------ Initialization ------------------------------
+
+void pccom_init()
+{
+  serialio_init();
+}
diff --git a/linear_pendulum_2009/avr/pccom.h b/linear_pendulum_2009/avr/pccom.h
new file mode 100644
index 0000000000000000000000000000000000000000..14c4c75d7da795a47f3e884364c2ab03e3e1353e
--- /dev/null
+++ b/linear_pendulum_2009/avr/pccom.h
@@ -0,0 +1,21 @@
+// pccom.h: Communication interface to PC via serialio_core.
+
+#ifndef __pccom_h
+#define __pccom_h
+
+#include <inttypes.h>
+#include "vel_control.h"
+
+void pccom_init();
+
+// Concurrency constraints:
+// Receiving and sending are mutually exclusive!
+void pccom_receiveByte(char ch);
+int16_t pccom_getNextByteToSend(); // returns -1 for nothing to send
+
+
+// ------------------------------- Callbacks ----------------------------------
+
+void serialio_putchar(unsigned char ch);
+
+#endif
diff --git a/linear_pendulum_2009/avr/serialio_core.h b/linear_pendulum_2009/avr/serialio_core.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ca09ae04477744fc4cec9bb34c4def7e70ca5cf
--- /dev/null
+++ b/linear_pendulum_2009/avr/serialio_core.h
@@ -0,0 +1,197 @@
+// serialio_core.h: Serialio protocol without the hardware bindings.
+
+#ifndef __serialio_core_h
+#define __serialio_core_h
+/*
+ * Digital in/out and poll commands are sent as one byte:
+ *
+ *   +-+-+-+-+-+-+-+-+
+ *   |0|0 0|  chan   | Bit clear
+ *   +-+-+-+-+-+-+-+-+
+ *
+ *   +-+-+-+-+-+-+-+-+
+ *   |0|0 1|  chan   | Bit set
+ *   +-+-+-+-+-+-+-+-+
+ *
+ *   +-+-+-+-+-+-+-+-+
+ *   |0|1 0|  chan   | Bit get
+ *   +-+-+-+-+-+-+-+-+
+ *
+ *   +-+-+-+-+-+-+-+-+
+ *   |0|1 1|  chan   | Channel get
+ *   +-+-+-+-+-+-+-+-+
+ *
+ *
+ * Channels are sent as 2 to 6 bytes, depending on resolution:
+ *
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+ * 2 |1| bit8...bit2 |  |0|bit|  chan   |
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+ *
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+ * 3 |1|bit15...bit9 |  |1| bit8...bit2 |  |0|bit|  chan   |
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+ *
+ *   ...
+ *
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+ 
+ * 6 |1|bit31...bit30|  |1|bit29...bit23| ... |0|bit|  chan   |
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+ 
+ *
+ *
+ *
+ * Channel 31 is special, as it serves as the configuration channel. When
+ * reading from it multiple responses are sent with the following layout
+ *
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * |           command specific data           |cmd|kind |conf chan|
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ *
+ *  kind: 000 == end of configuration
+ *        001 == digital in
+ *        010 == digital out
+ *        011 == analog in
+ *        100 == analog out
+ *        101 == counter in
+ *
+ *cmd == 0 (Resolution)
+ *
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * |                               | # of bits |0 0|kind |conf chan|
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ *
+ *  # of bits (1..32) 
+ *
+ *cmd == 1 (Minimum value)
+ *
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * |              minimum              |S| unit|0 1|kind |conf chan|
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * 
+ *  S (sign): 0 == +
+ *            1 == -
+ *  unit: 000 == V
+ *        001 == mV
+ *        010 == uV
+ *        100 == A
+ *
+ *cmd == 2 (Maximum value)
+ *
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * |              maximum              |S| unit|1 0|kind |conf chan|
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * 
+ *  S (sign): 0 == +
+ *            1 == -
+ *  unit: 000 == V
+ *        001 == mV
+ *        010 == uV
+ *        100 == A
+ */
+
+// ----------------------------- Interface -----------------------------------
+
+static void serialio_init();
+
+// ---- Receiving ----
+typedef enum { 
+  serialio_error, serialio_more, serialio_clearbit, serialio_setbit, 
+  serialio_setchannel, serialio_pollbit, serialio_pollchannel 
+} serialio_rxc_status;
+
+static serialio_rxc_status serialio_RXC(unsigned char ch); 
+
+// ----- Sending -----
+void serialio_putchar(unsigned char ch); // Callback
+
+static void serialio_putbit(unsigned char channel, unsigned char value);
+static void serialio_putchannel(unsigned char channel, unsigned long value);
+
+// ---- Configuration macros ----
+#define CONF_DIG_IN(channel) (0x20 | (channel)&0x1f)
+#define CONF_DIG_OUT(channel) (0x40 | (channel)&0x1f)
+
+#define CONF_END() serialio_putchannel(31, 0)
+#define CONF_DIGITAL_IN(chan, config) \
+  serialio_putchannel(31, (0x20|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_DIGITAL_OUT(chan, config) \
+  serialio_putchannel(31, (0x40|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_ANALOG_IN(chan, config) \
+  serialio_putchannel(31, (0x60|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_ANALOG_OUT(chan, config) \
+  serialio_putchannel(31, (0x80|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_ENCODER_IN(chan, config) \
+  serialio_putchannel(31, (0xa0|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_RESOLUTION(bits) (((bits)<<10)|0x000)
+#define CONF_MIN(value) ((value)|0x100)
+#define CONF_MAX(value) ((value)|0x200)
+#define CONF_NEGATIVE_VOLT(volt) (((long)(volt)<<14)|0x2000)
+#define CONF_POSITIVE_VOLT(volt) ((long)(volt)<<14)
+#define CONF_NEGATIVE_MILLIVOLT(millivolt) (((long)(millivolt)<<14)|0x2400)
+#define CONF_POSITIVE_MILLIVOLT(millivolt) ((long)(millivolt)<<14|0x400)
+#define CONF_POSITIVE_AMPERE(ampere) (((long)(ampere)<<14)|0x1000)
+
+
+// --------------------------- Implementation ---------------------------------
+
+static volatile unsigned long serialio_value;
+static volatile unsigned char serialio_channel, serialio_length;
+
+static void serialio_putbit(unsigned char channel, unsigned char value) 
+{
+  if (value) {
+    serialio_putchar(0x20 | (channel & 0x1f));
+  } else {
+    serialio_putchar(0x00 | (channel & 0x1f));
+  }
+}
+
+static void serialio_putchannel(unsigned char channel, unsigned long value) 
+{
+  if (value >= (1L<<30)) { serialio_putchar(0x80 | ((value >> 30) & 0x03)); }
+  if (value >= (1L<<23)) { serialio_putchar(0x80 | ((value >> 23) & 0x7f)); }
+  if (value >= (1L<<16)) { serialio_putchar(0x80 | ((value >> 16) & 0x7f)); }
+
+  if (value >= (1L<< 9)) { serialio_putchar(0x80 | ((value >> 9) & 0x7f)); }
+  //serialio_putchar(0x80 | ((value >> 9) & 0x7f)); // DEBUG
+
+  serialio_putchar(0x80 | ((value >> 2) & 0x7f));
+  serialio_putchar(((value << 5) & 0x60) | (channel & 0x1f));
+}
+
+static void serialio_init() 
+{
+  serialio_value = 0;
+  serialio_channel = 255;
+  serialio_length = 0;
+}
+
+static serialio_rxc_status serialio_RXC(unsigned char ch) {
+  unsigned char result = serialio_error;
+
+  if (serialio_length == 0) { serialio_value = 0; }
+  serialio_length++;
+  if ((ch & 0x80) == 0x80) {
+    // Collect yet another byte for later processing
+    serialio_value = (serialio_value << 7) | (ch & 0x7f);
+    result = serialio_more;
+  } else {
+    serialio_value = (serialio_value << 2) | ((ch & 0x60) >> 5);
+    serialio_channel = ch & 0x1f;
+    if (serialio_length == 1) {
+      switch (serialio_value & 0x03) {
+	// Digital output buffer (ULN2803A) is inverting
+	case 0: { result = serialio_clearbit; } break;
+	case 1: { result = serialio_setbit; } break;
+	case 2: { result = serialio_pollbit; } break;
+	case 3: { result = serialio_pollchannel; } break;
+      }
+    } else {
+      result = serialio_setchannel;
+    }
+    serialio_length = 0;
+  }
+  return result;
+}
+
+#endif
diff --git a/linear_pendulum_2009/avr/vel_control.c b/linear_pendulum_2009/avr/vel_control.c
index 17e6e1f192e4e2a58fb7f1188771ddb5f7382f4e..598efe7b5144fce399dfcfeebf31492d2ae36c59 100644
--- a/linear_pendulum_2009/avr/vel_control.c
+++ b/linear_pendulum_2009/avr/vel_control.c
@@ -5,11 +5,16 @@
 #include <inttypes.h>
 
 
+#include "pccom.h"
+#include "vel_control.h"
+
+
 // reference variables
 volatile int32_t ref = 0;  // 11 frac bits
 volatile int16_t refFlag = 0;
-volatile int16_t deltaRef = 2;
+volatile int16_t deltaRef = 1;
 volatile int16_t refCount = 0;
+volatile int32_t refTest = 0;
 
 
 // velocity control variables
@@ -61,6 +66,17 @@ static inline void sendData() {
 }
 
 
+// return position (in tics) 
+int32_t getPosition() {
+  return pos;
+}
+
+
+// return velocity (in mm/s) 
+int32_t getVelocity() {
+  return velEst;
+}
+
 
 /* Routine used to set the red LED */
 void setLED(uint8_t on)
@@ -69,6 +85,12 @@ void setLED(uint8_t on)
   else PORTB |= 0x80;     //Turn off
 }
 
+// Set new reference value
+void setRef(int32_t newRef) {
+  ref = newRef;
+}
+
+
 /* Routine used to initialize the positional encoders */
 void initPos()
 {
@@ -157,6 +179,9 @@ SIGNAL(SIG_OUTPUT_COMPARE0) {
     u = -128;
   }
 
+  //u = 2;
+
+  /*
   // reference calculations
   refCount++;
   
@@ -177,7 +202,7 @@ SIGNAL(SIG_OUTPUT_COMPARE0) {
       deltaRef = -deltaRef;
     }
   }
-  
+  */
 
   /*
   if (refCount == 1000) {
@@ -186,7 +211,7 @@ SIGNAL(SIG_OUTPUT_COMPARE0) {
   */
 
   
-  pos = pos*(1-brake);
+  ref = ref*(1-brake);
 
   
   // TWI-communication
@@ -211,29 +236,29 @@ SIGNAL(SIG_OUTPUT_COMPARE0) {
   // stop transmission
   outp(BV(TWINT)|BV(TWEN)|BV(TWSTO),TWCR);
 
-
-  
-  //velEstTemp = velEst;
-  /*
-  putchar((unsigned char) ((((velEstTemp+16)>>5)&0x0000ff00)>>8));
-  putchar((unsigned char) (((velEstTemp+16)>>5)&0x000000ff));
-
-  //putchar((unsigned char) ((deltaPos&0xff00)>>8));
-  //putchar((unsigned char) (deltaPos&0x00ff));
-  */
-  
-  putchar((unsigned char) ((velEst&0xff000000)>>24));
-  putchar((unsigned char) ((velEst&0x00ff0000)>>16));
-
-  putchar((unsigned char) ((velEst&0x0000ff00)>>8));
-  putchar((unsigned char) (velEst&0x000000ff));
-
-  putchar((unsigned char) ((I&0xff000000)>>24));
-  putchar((unsigned char) ((I&0x00ff0000)>>16));
-
-  putchar((unsigned char) ((I&0x0000ff00)>>8));
-  putchar((unsigned char) (I&0x000000ff));
+  // ------- Noncritical section -------
+
+  // Poll UART receiver
+  uint8_t status = UCSRA;
+  if (status & (1<<RXC)) {
+    char ch = UDR;
+    pccom_receiveByte(ch);
+    
+    if (status & ((1<<FE)|(1<<DOR)|(1<<PE))) { 
+      //main_emergencyStop(); // stop on USART error
+    }     
+  }
   
+  // Poll UART sender
+  if (UCSRA & (1<<UDRE)) {
+    int16_t toSend = pccom_getNextByteToSend();
+    //if (toSend >= 0) UDR = (char)toSend;
+    while (toSend >= 0) {
+      UDR = (char)toSend;
+      while ((UCSRA & (1<<UDRE)) == 0) {} // send all data in buffer
+      toSend = pccom_getNextByteToSend();
+    }
+  }
 
   PORTC &= ~0x10;  
 
@@ -267,7 +292,7 @@ int main()
   
   //Serial communication
   outp(0x00, UCSRA);	// USART:
-  outp(0x98, UCSRB);	// USART: RxIntEnable|RxEnable|TxEnable
+  outp(0x18, UCSRB);	// USART: RxEnable|TxEnable
   outp(0x86, UCSRC);	// USART: 8bit, no parity
   outp(0x00, UBRRH);	// USART: 115200 @ 14.7456MHz
   outp(7,UBRRL);	// USART: 115200 @ 14.7456MHz
@@ -287,6 +312,8 @@ int main()
 
   // initialize position measurements
   initPos();
+
+  pccom_init();
   
   //Enable interrupts
   sei();
diff --git a/linear_pendulum_2009/avr/vel_control.h b/linear_pendulum_2009/avr/vel_control.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ffacdd4e424206f19e9fa35df680db9b5262bd9
--- /dev/null
+++ b/linear_pendulum_2009/avr/vel_control.h
@@ -0,0 +1,9 @@
+#ifndef __vel_control_h
+#define __vel_control_h
+
+
+void setRef(int32_t newRef);
+int32_t getPosition();
+int32_t getVelocity();
+
+#endif