diff --git a/Makefile b/Makefile
index 10c124cc3068c0eec4b27d69b8541ad79aa8bbeb..bcd2b90d9dea83aae33e1d611c89688b941ff20f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 DEVICE     = atxmega64a3u
 PROGRAMMER = -c avrispmkII
-OBJECTS    = main.o clock.o debug.o
+OBJECTS    = main.o clock.o debug.o bus.o
 PORT		= usb
 
 # For computing fuse byte values for other devices and options see
diff --git a/avrxmegastuff b/avrxmegastuff
index 870d9cb57ca40c8ee6161be375553aa722ec22ff..9b92a602eb7145ca70167555cd3cb7d36b742ead 160000
--- a/avrxmegastuff
+++ b/avrxmegastuff
@@ -1 +1 @@
-Subproject commit 870d9cb57ca40c8ee6161be375553aa722ec22ff
+Subproject commit 9b92a602eb7145ca70167555cd3cb7d36b742ead
diff --git a/bus.c b/bus.c
new file mode 100644
index 0000000000000000000000000000000000000000..96c099e6e1823d460521696eacea2b7bd3ed1229
--- /dev/null
+++ b/bus.c
@@ -0,0 +1,183 @@
+#include "common.h"
+
+/*[[[cog
+import conf
+import avrxmegastuff as ams
+]]]*/
+//[[[end]]]
+
+
+/*[[[cog
+cog.out(
+    ams.rs485(
+        prefix="bus",
+        **conf.BUS,
+        header=False,
+    )
+)
+]]]*/
+    volatile uint8_t bus_txbuffer[BUS_txlen];
+    volatile uint16_t bus_txidxB;
+    volatile uint16_t bus_txidxA;
+
+    volatile uint8_t bus_rxbuffer[BUS_rxlen];
+    volatile uint16_t bus_rxidx;
+
+void bus_init()
+{
+    BUS_port.OUTSET = BUS_txpin;
+    BUS_port.DIRSET = BUS_txpin;
+    BUS_deport.DIRSET = BUS_depin;
+    BUS_deport.OUTCLR = BUS_depin;
+
+    uint16_t bscale = 0;
+    if(BUS_baudrate<600)
+        bscale++;
+    if(BUS_baudrate<300)
+        bscale++;
+    if(BUS_baudrate<150)
+        bscale++;
+    if(BUS_baudrate<75)
+        bscale++;
+    if(BUS_baudrate<36)
+        bscale++;
+    if(BUS_baudrate<18)
+        bscale++;
+    if(BUS_baudrate<9)
+        bscale++;
+
+    uint16_t bsel = (F_CPU-((((uint32_t)8)<<bscale) * BUS_baudrate)) / ((((uint32_t)16)<<bscale) * BUS_baudrate);
+
+    BUS_USART.BAUDCTRLA = bsel;
+    BUS_USART.BAUDCTRLB = (bscale << USART_BSCALE_gp) | (bsel >> 8);
+
+    BUS_USART.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc;
+    if(BUS_chsize==5)
+        BUS_USART.CTRLC |= USART_CHSIZE_5BIT_gc;
+    else if(BUS_chsize==6)
+        BUS_USART.CTRLC |= USART_CHSIZE_6BIT_gc;
+    else if(BUS_chsize==7)
+        BUS_USART.CTRLC |= USART_CHSIZE_7BIT_gc;
+    else if(BUS_chsize==8)
+        BUS_USART.CTRLC |= USART_CHSIZE_8BIT_gc;
+    else
+        BUS_USART.CTRLC |= USART_CHSIZE_9BIT_gc;
+    BUS_USART.CTRLA = (BUS_rxen?USART_RXCINTLVL_MED_gc:USART_RXCINTLVL_OFF_gc)|(BUS_txen?USART_TXCINTLVL_MED_gc:0x00);
+    BUS_USART.CTRLB = (BUS_rxen?USART_RXEN_bm:0x00) | (BUS_txen?USART_TXEN_bm:0x00);
+}
+
+ISR(BUS_RXC_vect)
+{
+    uint8_t received = BUS_USART.DATA;
+    if(received==BUS_rxtrigger)
+    {
+        bus_rxbuffer[bus_rxidx]=0;
+        bus_msg_handler((char*)bus_rxbuffer);
+        bus_rxidx=0;
+    }
+    else
+    {
+        bus_rxbuffer[bus_rxidx] = received;
+        bus_rxidx++;
+        if(bus_rxidx>=BUS_rxlen)
+            bus_rxidx=0;
+    }
+}
+    
+ISR(BUS_DRE_vect)
+{
+    BUS_deport.OUTSET = BUS_depin;
+    if(bus_txidxA == bus_txidxB)
+    {
+        // empty
+        BUS_USART.CTRLA = (BUS_USART.CTRLA & ~USART_DREINTLVL_gm) | USART_DREINTLVL_OFF_gc;
+    }
+    else
+    {
+        BUS_USART.DATA = bus_txbuffer[bus_txidxA];
+        bus_txidxA++;
+        bus_txidxA%=BUS_txlen;
+    }
+}
+
+ISR(BUS_TXC_vect)
+  {
+      BUS_deport.OUTCLR = BUS_depin;
+  }
+
+void bus_putchar(uint8_t ch)
+{
+    while((bus_txidxB+1)%BUS_txlen == bus_txidxA);
+
+    bus_txbuffer[bus_txidxB] = ch;
+    bus_txidxB++;
+    bus_txidxB%=BUS_txlen;
+
+    BUS_USART.CTRLA = (BUS_USART.CTRLA & ~USART_DREINTLVL_gm) | USART_DREINTLVL_MED_gc;
+}
+
+void bus_putzchar(const char* zchar)
+{
+    uint16_t i=0;
+    while(zchar[i]!=0)
+    {
+        bus_putchar(zchar[i]);
+        i++;
+    }
+}
+
+void bus_putfloat(const float f, uint8_t decsize)
+{
+    int32_t fl;
+
+    char buf[64];
+    
+    if(decsize>0)
+    {
+        fl=f;
+        float decimal = f-fl;
+        if(decimal<0)
+            decimal*=-1;
+        
+        char bufformat[64];
+        uint8_t i;
+        for(i=0;i<decsize;i++)
+            decimal*=10;
+        int16_t n;
+        n = snprintf(bufformat,64,"%%li.%%0%ulu",decsize);
+        if(n<64)
+        {
+            n = snprintf(buf,64,bufformat,fl,(uint32_t)(decimal));
+            if(n<63)
+                bus_putzchar(buf);
+        }
+    }
+    else
+    {
+        if(f>=0)
+            fl = f+.5;
+        else
+            fl = f-.5;
+
+        int16_t n = snprintf(buf,64,"%li.",fl);
+        if(n<63)
+            bus_putzchar(buf);
+    }
+}
+
+void bus_printf(const char *fmt, ...)
+{
+    char buf[BUS_txlen];
+
+    va_list ap;
+    va_start(ap, fmt);
+    int16_t n = vsnprintf(buf, BUS_txlen, fmt, ap);
+    va_end(ap);
+
+    if (n < BUS_txlen)
+        bus_putzchar(buf);
+}
+///[[[end]]]
+
+void bus_msg_handler(const char * msg)
+{}
diff --git a/bus.h b/bus.h
new file mode 100644
index 0000000000000000000000000000000000000000..267ecba34b13013e9a675354695603fbd3636930
--- /dev/null
+++ b/bus.h
@@ -0,0 +1,55 @@
+#include "common.h"
+
+/*[[[cog
+import conf
+import avrxmegastuff as ams
+]]]*/
+//[[[end]]]
+
+
+/*[[[cog
+cog.out(
+    ams.rs485(
+        prefix="bus",
+        **conf.BUS,
+        header=True,
+    )
+)
+]]]*/
+#ifndef H_UART_bus
+#define H_UART_bus 1
+
+#define BUS_port PORTC
+#define BUS_txpin PIN3_bm
+#define BUS_rxlen 256
+#define BUS_txlen 256
+#define BUS_baudrate 9600
+#define BUS_chsize 8
+#define BUS_rxtrigger '\n'
+#define BUS_rxen true
+#define BUS_txen true
+#define BUS_USART USARTC0
+#define BUS_DRE_vect USARTC0_DRE_vect
+#define BUS_RXC_vect USARTC0_RXC_vect
+#define BUS_TXC_vect USARTC0_TXC_vect
+#define BUS_deport PORTC
+#define BUS_depin PIN0_bm
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+void bus_init();
+
+void bus_putchar(uint8_t ch);
+void bus_putzchar(const char* zchar);
+void bus_putfloat(const float f, uint8_t decsize);
+void bus_printf(const char *fmt, ...);
+
+void bus_msg_handler(const char *msg);
+#endif
+///[[[end]]]
diff --git a/common.h b/common.h
index 9d32c2e836cd3c7d1eb1b394d3e1df9ef26cc42b..0a1915a61efcd5f9b151150d3a13682d2fbd2d45 100644
--- a/common.h
+++ b/common.h
@@ -10,10 +10,7 @@
 
 #include "commitid.h"
 #include "clock.h"
-#include "config.h"
-#include "thermometer.h"
-#include "vanne.h"
-#include "median_filter.h"
-#include "leds.h"
+#include "debug.h"
+#include "bus.h"
 
 #endif
diff --git a/conf.py b/conf.py
index 410b3d784cf7fd40ef923c3490211cad50f355a2..7c0a4d75fff2975afd68ae197f02cee9d6425361 100644
--- a/conf.py
+++ b/conf.py
@@ -30,7 +30,11 @@ LED = {
 
 DEBUG = {"name": "C1", "txpin": 7, "tx": True}
 
-BUS = {"name": "C0", "txpin": 3, "tx": True, "rx": True, "de_pindesc": PinDesc("C0")}
+BUS = {"name": "C0", "txpin": 3, "tx": True,
+        "rx": True, "de_pindesc": PinDesc("C0"),
+        "rxhandler": "bus_msg_handler",
+        "txlen": 256, "rxlen": 256,
+        "bandrate": 1200}
 
 THERMO_PERIOD = 5
 THERMO_MEDIAN_FILTER_LEN = 13
diff --git a/config.h b/config.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f2bc138ea330a64d76648eda5bc026652745146
--- /dev/null
+++ b/config.h
@@ -0,0 +1,55 @@
+#include "common.h"
+
+#ifndef CONFIG_H
+#define CONFIG_H 1
+
+typedef enum mode_enum
+{
+    MODE_FORCE_CLOSE = 0x01,
+    MODE_FORCE_OPEN = 0x02,
+    MODE_FORCE_VIDANGE = 0x03,
+    MODE_DEBIT = 0x04,
+    MODE_AUTO = 0x05,
+} mode_t;
+
+typedef struct config_struct
+{
+    uint8_t mode;
+    uint16_t vol_cuve;
+    uint16_t Kp;
+    uint16_t ti;
+    int16_t consigne_temperature;
+    uint16_t debit_max;
+    uint8_t cst_ev;
+    uint16_t debit_min1;
+    uint16_t debit_min2;
+    uint8_t minimum_step;
+    uint16_t volume_manque_max;
+    uint8_t m_rattrapage;
+} config_t;
+
+typedef struct config_calc_struct
+{
+    mode_t mode;
+    float vol_cuve;
+    float Kp;
+    float ti;
+    float consigne_temperature;
+    float debit_max;
+    float cst_ev;
+    float debit_min1;
+    float debit_min2;
+    uint16_t minimum_step;
+    float debit_no_action;
+    float volume_manque_max;
+    float m_rattrapage;
+} config_calc_t;
+
+void config_read();
+void config_write();
+void config_calc_update();
+
+extern config_t config;
+extern config_calc_t config_calc;
+
+#endif
diff --git a/define_commit_id.py b/define_commit_id.py
new file mode 100755
index 0000000000000000000000000000000000000000..fca0bb7774d34b5f66b3b1dbceccd0c2021ebf49
--- /dev/null
+++ b/define_commit_id.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python3
+
+import os
+import time
+import subprocess
+
+CMDCOMMIT = ('git', 'describe', '--abbr=5', '--dirty=+')
+
+def retain_out(x):
+    return subprocess.check_output(x).strip().decode('utf8')
+
+if False:
+    commit = retain_out(CMDCOMMIT)
+    mts = max(os.path.getmtime(x) for x in os.listdir() if x.endswith('.c') or x.endswith('.h') or x.endswith('.py'))
+    mtime = time.strftime('%Y-%m-%d %H:%M',time.localtime(mts))
+    print(f'#define COMMITID_LINE0 "{commit}"')
+    print(f'#define COMMITID_LINE1 "{mtime}"')
+
+if __name__ == '__main__':
+    print(f'#define COMMITID_MAJOR 0')
+    print(f'#define COMMITID_MINOR 0')
+    print(f'#define COMMITID_NBCOMMITS 0x78')
+    print(f'#define COMMITID_HASH 0xB00B')
+    print(f'#define COMMITID_DIRTY 7')
diff --git a/main.c b/main.c
index 86ab1d75a2ed5ff86cf9a40d4f48dad1d12b476d..471d822d827c95c0e39a6795f2b3ab48d8cfbe10 100644
--- a/main.c
+++ b/main.c
@@ -6,25 +6,18 @@ int main(void)
     PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
     sei();
 
-    btn_init();
     debug_init();
-    lcd_init();
-    vanne_init();
-    config_init();
-    debit_init();
-    status_init();
-    main_timer_init();
-    led_init();
+    //lcd_init();
+    //vanne_init();
+    //config_init();
+    //debit_init();
+    //status_init();
+    //main_timer_init();
+    //led_init();
 
-    lcd_write_lines("Projet BCS", "Par J.-B. Leger");
-    _delay_ms(4000);
-
-    lcd_write_lines(COMMITID_LINE0, COMMITID_LINE1);
-    _delay_ms(4000);
-     
     while(1)
     {
-        do_orders();
+        //do_orders();
         _delay_ms(10);
     }
 }