François Gautrais před 8 roky
rodič
revize
27e1bb1cd5
18 změnil soubory, kde provedl 1606 přidání a 77 odebrání
  1. 1 1
      Makefile
  2. 3 3
      MakefileRpi
  3. 726 0
      VirtualWire.c
  4. 301 0
      VirtualWire.h
  5. 420 24
      backend.c
  6. 1 0
      backend.h
  7. 37 5
      bus.c
  8. 4 4
      config.c
  9. 8 7
      config.cfg
  10. 7 8
      io.h
  11. 2 4
      mount.c
  12. 9 9
      recv.c
  13. 50 0
      send.c
  14. 2 1
      server/db.c
  15. 23 8
      server/db_access.c
  16. 1 2
      stub.c
  17. 0 1
      timer.c
  18. 11 0
      timer.h

+ 1 - 1
Makefile

@@ -1,4 +1,4 @@
-OBJ=bus.o stub.o timer.o send.o
+OBJ=bus.o stub.o timer.o send.o VirtualWire.o
 TARGET=send
 CC=avr-gcc
 OBJCOPY=$(CROSS_COMPILE)avr-objcopy

+ 3 - 3
MakefileRpi

@@ -1,12 +1,12 @@
 OBJ=bus.o stub.o timer.o recv.o backend.o config.o mount.o
 TARGET=recv
-#CROSS_COMPILE=/home/ptitcois/Programmation/rpi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
+CROSS_COMPILE=/home/ptitcois/Programmation/rpi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
 CC=$(CROSS_COMPILE)gcc
 OBJCOPY=$(CROSS_COMPILE)objcopy
 
-CFLAGS= -g 
+CFLAGS= -g -Wall
 
-LDFLAGS= -lpthread -Llib -lrt
+LDFLAGS= -lpthread -Llib -lrt 
 
 all: $(TARGET)
 

+ 726 - 0
VirtualWire.c

@@ -0,0 +1,726 @@
+// VirtualWire.cpp
+//
+// Virtual Wire implementation for Arduino
+// See the README file in this directory fdor documentation
+// See also
+// ASH Transceiver Software Designer's Guide of 2002.08.07
+//   http://www.rfm.com/products/apnotes/tr_swg05.pdf
+//
+// Changes:
+// 1.5 2008-05-25: fixed a bug that could prevent messages with certain
+//  bytes sequences being received (false message start detected)
+// 1.6 2011-09-10: Patch from David Bath to prevent unconditional reenabling of the receiver
+//  at end of transmission.
+//
+// Author: Mike McCauley (mikem@airspayce.com)
+// Copyright (C) 2008 Mike McCauley
+// $Id: VirtualWire.cpp,v 1.9 2013/02/14 22:02:11 mikem Exp mikem $
+
+
+#if defined(ARDUINO)
+ #if (ARDUINO < 100)
+  #include "WProgram.h"
+ #endif
+#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
+ #include "legacymsp430.h"
+ #include "Energia.h"
+#else // error
+ #error Platform not defined
+#endif
+
+#include "VirtualWire.h"
+#include <stdint.h>
+
+#define lo8(x) ((x)&0xff) 
+#define hi8(x) ((x)>>8)
+
+    uint16_t crc16_update(uint16_t crc, uint8_t a)
+    {
+	int i;
+
+	crc ^= a;
+	for (i = 0; i < 8; ++i)
+	{
+	    if (crc & 1)
+		crc = (crc >> 1) ^ 0xA001;
+	    else
+		crc = (crc >> 1);
+	}
+
+	return crc;
+    }
+
+    uint16_t crc_xmodem_update (uint16_t crc, uint8_t data)
+    {
+        int i;
+
+        crc = crc ^ ((uint16_t)data << 8);
+        for (i=0; i<8; i++)
+        {
+            if (crc & 0x8000)
+                crc = (crc << 1) ^ 0x1021;
+            else
+                crc <<= 1;
+        }
+
+        return crc;
+    }
+    uint16_t _crc_ccitt_update (uint16_t crc, uint8_t data)
+    {
+        data ^= lo8 (crc);
+        data ^= data << 4;
+
+        return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4) 
+                ^ ((uint16_t)data << 3));
+    }
+
+    uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data)
+    {
+	uint8_t i;
+
+	crc = crc ^ data;
+	for (i = 0; i < 8; i++)
+	{
+	    if (crc & 0x01)
+	        crc = (crc >> 1) ^ 0x8C;
+	    else
+	        crc >>= 1;
+	}
+
+	return crc;
+    }
+
+
+
+
+static uint8_t vw_tx_buf[(VW_MAX_MESSAGE_LEN * 2) + VW_HEADER_LEN] 
+     = {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c};
+
+// Number of symbols in vw_tx_buf to be sent;
+static uint8_t vw_tx_len = 0;
+
+// Index of the next symbol to send. Ranges from 0 to vw_tx_len
+static uint8_t vw_tx_index = 0;
+
+// Bit number of next bit to send
+static uint8_t vw_tx_bit = 0;
+
+// Sample number for the transmitter. Runs 0 to 7 during one bit interval
+static uint8_t vw_tx_sample = 0;
+
+// Flag to indicated the transmitter is active
+static volatile uint8_t vw_tx_enabled = 0;
+
+// Total number of messages sent
+static uint16_t vw_tx_msg_count = 0;
+
+// The digital IO pin number of the press to talk, enables the transmitter hardware
+static uint8_t vw_ptt_pin = 10;
+static uint8_t vw_ptt_inverted = 0;
+
+// The digital IO pin number of the receiver data
+static uint8_t vw_rx_pin = 11;
+
+// The digital IO pin number of the transmitter data
+static uint8_t vw_tx_pin = 12;
+
+// Current receiver sample
+static uint8_t vw_rx_sample = 0;
+
+// Last receiver sample
+static uint8_t vw_rx_last_sample = 0;
+
+// PLL ramp, varies between 0 and VW_RX_RAMP_LEN-1 (159) over 
+// VW_RX_SAMPLES_PER_BIT (8) samples per nominal bit time. 
+// When the PLL is synchronised, bit transitions happen at about the
+// 0 mark. 
+static uint8_t vw_rx_pll_ramp = 0;
+
+// This is the integrate and dump integral. If there are <5 0 samples in the PLL cycle
+// the bit is declared a 0, else a 1
+static uint8_t vw_rx_integrator = 0;
+
+// Flag indictate if we have seen the start symbol of a new message and are
+// in the processes of reading and decoding it
+static uint8_t vw_rx_active = 0;
+
+// Flag to indicate that a new message is available
+static volatile uint8_t vw_rx_done = 0;
+
+// Flag to indicate the receiver PLL is to run
+static uint8_t vw_rx_enabled = 0;
+
+// Last 12 bits received, so we can look for the start symbol
+static uint16_t vw_rx_bits = 0;
+
+// How many bits of message we have received. Ranges from 0 to 12
+static uint8_t vw_rx_bit_count = 0;
+
+// The incoming message buffer
+static uint8_t vw_rx_buf[VW_MAX_MESSAGE_LEN];
+
+// The incoming message expected length
+static uint8_t vw_rx_count = 0;
+
+// The incoming message buffer length received so far
+static volatile uint8_t vw_rx_len = 0;
+
+// Number of bad messages received and dropped due to bad lengths
+static uint8_t vw_rx_bad = 0;
+
+// Number of good messages received
+static uint8_t vw_rx_good = 0;
+
+// 4 bit to 6 bit symbol converter table
+// Used to convert the high and low nybbles of the transmitted data
+// into 6 bit symbols for transmission. Each 6-bit symbol has 3 1s and 3 0s 
+// with at most 3 consecutive identical bits
+static uint8_t symbols[] =
+{
+    0xd,  0xe,  0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 
+    0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34
+};
+
+// Cant really do this as a real C++ class, since we need to have 
+
+
+// Compute CRC over count bytes.
+// This should only be ever called at user level, not interrupt level
+uint16_t vw_crc(uint8_t *ptr, uint8_t count)
+{
+    uint16_t crc = 0xffff;
+
+    while (count-- > 0) 
+	crc = _crc_ccitt_update(crc, *ptr++);
+    return crc;
+}
+
+// Convert a 6 bit encoded symbol into its 4 bit decoded equivalent
+uint8_t vw_symbol_6to4(uint8_t symbol)
+{
+    uint8_t i;
+    
+    // Linear search :-( Could have a 64 byte reverse lookup table?
+    for (i = 0; i < 16; i++)
+	if (symbol == symbols[i]) return i;
+    return 0; // Not found
+}
+
+// Set the output pin number for transmitter data
+void vw_set_tx_pin(uint8_t pin)
+{
+    vw_tx_pin = pin;
+}
+
+// Set the pin number for input receiver data
+void vw_set_rx_pin(uint8_t pin)
+{
+    vw_rx_pin = pin;
+}
+
+// Set the output pin number for transmitter PTT enable
+void vw_set_ptt_pin(uint8_t pin)
+{
+    vw_ptt_pin = pin;
+}
+
+// Set the ptt pin inverted (low to transmit)
+void vw_set_ptt_inverted(uint8_t inverted)
+{
+    vw_ptt_inverted = inverted;
+}
+
+// Called 8 times per bit period
+// Phase locked loop tries to synchronise with the transmitter so that bit 
+// transitions occur at about the time vw_rx_pll_ramp is 0;
+// Then the average is computed over each bit period to deduce the bit value
+void vw_pll()
+{
+    // Integrate each sample
+    if (vw_rx_sample)
+	vw_rx_integrator++;
+
+    if (vw_rx_sample != vw_rx_last_sample)
+    {
+	// Transition, advance if ramp > 80, retard if < 80
+	vw_rx_pll_ramp += ((vw_rx_pll_ramp < VW_RAMP_TRANSITION) 
+			   ? VW_RAMP_INC_RETARD 
+			   : VW_RAMP_INC_ADVANCE);
+	vw_rx_last_sample = vw_rx_sample;
+    }
+    else
+    {
+	// No transition
+	// Advance ramp by standard 20 (== 160/8 samples)
+	vw_rx_pll_ramp += VW_RAMP_INC;
+    }
+    if (vw_rx_pll_ramp >= VW_RX_RAMP_LEN)
+    {
+	// Add this to the 12th bit of vw_rx_bits, LSB first
+	// The last 12 bits are kept
+	vw_rx_bits >>= 1;
+
+	// Check the integrator to see how many samples in this cycle were high.
+	// If < 5 out of 8, then its declared a 0 bit, else a 1;
+	if (vw_rx_integrator >= 5)
+	    vw_rx_bits |= 0x800;
+
+	vw_rx_pll_ramp -= VW_RX_RAMP_LEN;
+	vw_rx_integrator = 0; // Clear the integral for the next cycle
+
+	if (vw_rx_active)
+	{
+	    // We have the start symbol and now we are collecting message bits,
+	    // 6 per symbol, each which has to be decoded to 4 bits
+	    if (++vw_rx_bit_count >= 12)
+	    {
+		// Have 12 bits of encoded message == 1 byte encoded
+		// Decode as 2 lots of 6 bits into 2 lots of 4 bits
+		// The 6 lsbits are the high nybble
+		uint8_t this_byte = 
+		    (vw_symbol_6to4(vw_rx_bits & 0x3f)) << 4 
+		    | vw_symbol_6to4(vw_rx_bits >> 6);
+
+		// The first decoded byte is the byte count of the following message
+		// the count includes the byte count and the 2 trailing FCS bytes
+		// REVISIT: may also include the ACK flag at 0x40
+		if (vw_rx_len == 0)
+		{
+		    // The first byte is the byte count
+		    // Check it for sensibility. It cant be less than 4, since it
+		    // includes the bytes count itself and the 2 byte FCS
+		    vw_rx_count = this_byte;
+		    if (vw_rx_count < 4 || vw_rx_count > VW_MAX_MESSAGE_LEN)
+		    {
+			// Stupid message length, drop the whole thing
+			vw_rx_active = false;
+			vw_rx_bad++;
+                        return;
+		    }
+		}
+		vw_rx_buf[vw_rx_len++] = this_byte;
+
+		if (vw_rx_len >= vw_rx_count)
+		{
+		    // Got all the bytes now
+		    vw_rx_active = false;
+		    vw_rx_good++;
+		    vw_rx_done = true; // Better come get it before the next one starts
+		}
+		vw_rx_bit_count = 0;
+	    }
+	}
+	// Not in a message, see if we have a start symbol
+	else if (vw_rx_bits == 0xb38)
+	{
+	    // Have start symbol, start collecting message
+	    vw_rx_active = true;
+	    vw_rx_bit_count = 0;
+	    vw_rx_len = 0;
+	    vw_rx_done = false; // Too bad if you missed the last message
+	}
+    }
+}
+
+// Common function for setting timer ticks @ prescaler values for speed
+// Returns prescaler index into {0, 1, 8, 64, 256, 1024} array
+// and sets nticks to compare-match value if lower than max_ticks
+// returns 0 & nticks = 0 on fault
+static uint8_t _timer_calc(uint16_t speed, uint16_t max_ticks, uint16_t *nticks)
+{
+    // Clock divider (prescaler) values - 0/3333: error flag
+    uint16_t prescalers[] = {0, 1, 8, 64, 256, 1024, 3333};
+    uint8_t prescaler=0; // index into array & return bit value
+    unsigned long ulticks; // calculate by ntick overflow
+
+    // Div-by-zero protection
+    if (speed == 0)
+    {
+        // signal fault
+        *nticks = 0;
+        return 0;
+    }
+
+    // test increasing prescaler (divisor), decreasing ulticks until no overflow
+    for (prescaler=1; prescaler < 7; prescaler += 1)
+    {
+        // Amount of time per CPU clock tick (in seconds)
+        float clock_time = (1.0 / (((float)F_CPU) / (float)(prescalers[prescaler])));
+        // Fraction of second needed to xmit one bit
+        float bit_time = ((1.0 / ((float)speed)) / 8.0);
+        // number of prescaled ticks needed to handle bit time @ speed
+        ulticks = (long)(bit_time / clock_time);
+        // Test if ulticks fits in nticks bitwidth (with 1-tick safety margin)
+        if ((ulticks > 1) && (ulticks < max_ticks))
+        {
+            break; // found prescaler
+        }
+        // Won't fit, check with next prescaler value
+    }
+
+    // Check for error
+    if ((prescaler == 6) || (ulticks < 2) || (ulticks > max_ticks))
+    {
+        // signal fault
+        *nticks = 0;
+        return 0;
+    }
+
+    *nticks = ulticks;
+    return prescaler;
+}
+
+#if defined(__arm__) && defined(CORE_TEENSY)
+  // This allows the AVR interrupt code below to be run from an
+  // IntervalTimer object.  It must be above vw_setup(), so the
+  // the TIMER1_COMPA_vect function name is defined.
+  #ifdef SIGNAL
+  #undef SIGNAL
+  #endif
+  #define SIGNAL(f) void f(void)
+  #ifdef TIMER1_COMPA_vect
+  #undef TIMER1_COMPA_vect
+  #endif
+  void TIMER1_COMPA_vect(void);
+#endif
+
+
+// Speed is in bits per sec RF rate
+#if defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
+void vw_setup(uint16_t speed)
+{
+	// Calculate the counter overflow count based on the required bit speed
+	// and CPU clock rate
+	uint16_t ocr1a = (F_CPU / 8UL) / speed;
+		
+	// This code is for Energia/MSP430
+	TA0CCR0 = ocr1a;				// Ticks for 62,5 us
+	TA0CTL = TASSEL_2 + MC_1;       // SMCLK, up mode
+	TA0CCTL0 |= CCIE;               // CCR0 interrupt enabled
+		
+	// Set up digital IO pins
+	pinMode(vw_tx_pin, OUTPUT);
+	pinMode(vw_rx_pin, INPUT);
+	pinMode(vw_ptt_pin, OUTPUT);
+	digitalWrite(vw_ptt_pin, vw_ptt_inverted);
+}	
+
+#elif defined (ARDUINO) // Arduino specific
+void vw_setup(uint16_t speed)
+{
+    uint16_t nticks; // number of prescaled ticks needed
+    uint8_t prescaler; // Bit values for CS0[2:0]
+
+#ifdef __AVR_ATtiny85__
+    // figure out prescaler value and counter match value
+    prescaler = _timer_calc(speed, (uint8_t)-1, &nticks);
+    if (!prescaler)
+    {
+        return; // fault
+    }
+
+    TCCR0A = 0;
+    TCCR0A = _BV(WGM01); // Turn on CTC mode / Output Compare pins disconnected
+
+    // convert prescaler index to TCCRnB prescaler bits CS00, CS01, CS02
+    TCCR0B = 0;
+    TCCR0B = prescaler; // set CS00, CS01, CS02 (other bits not needed)
+
+    // Number of ticks to count before firing interrupt
+    OCR0A = (uint8_t)nticks;
+
+    // Set mask to fire interrupt when OCF0A bit is set in TIFR0
+    TIMSK |= _BV(OCIE0A);
+
+#elif defined(__arm__) && defined(CORE_TEENSY)
+    // on Teensy 3.0 (32 bit ARM), use an interval timer
+    IntervalTimer *t = new IntervalTimer();
+    t->begin(TIMER1_COMPA_vect, 125000.0 / (float)(speed));
+
+#else // ARDUINO
+    // This is the path for most Arduinos
+    // figure out prescaler value and counter match value
+    prescaler = _timer_calc(speed, (uint16_t)-1, &nticks);
+    if (!prescaler)
+    {
+        return; // fault
+    }
+
+    TCCR1A = 0; // Output Compare pins disconnected
+    TCCR1B = _BV(WGM12); // Turn on CTC mode
+
+    // convert prescaler index to TCCRnB prescaler bits CS10, CS11, CS12
+    TCCR1B |= prescaler;
+
+    // Caution: special procedures for setting 16 bit regs
+    // is handled by the compiler
+    OCR1A = nticks;
+    // Enable interrupt
+#ifdef TIMSK1
+    // atmega168
+    TIMSK1 |= _BV(OCIE1A);
+#else
+    // others
+    TIMSK |= _BV(OCIE1A);
+#endif // TIMSK1
+
+#endif // __AVR_ATtiny85__
+
+    // Set up digital IO pins
+    pinMode(vw_tx_pin, OUTPUT);
+    pinMode(vw_rx_pin, INPUT);
+    pinMode(vw_ptt_pin, OUTPUT);
+    digitalWrite(vw_ptt_pin, vw_ptt_inverted);
+}
+
+#endif // ARDUINO
+
+// Start the transmitter, call when the tx buffer is ready to go and vw_tx_len is
+// set to the total number of symbols to send
+void vw_tx_start()
+{
+    vw_tx_index = 0;
+    vw_tx_bit = 0;
+    vw_tx_sample = 0;
+
+    // Enable the transmitter hardware
+    digitalWrite(vw_ptt_pin, true ^ vw_ptt_inverted);
+
+    // Next tick interrupt will send the first bit
+    vw_tx_enabled = true;
+}
+
+// Stop the transmitter, call when all bits are sent
+void vw_tx_stop()
+{
+    // Disable the transmitter hardware
+    digitalWrite(vw_ptt_pin, false ^ vw_ptt_inverted);
+    digitalWrite(vw_tx_pin, false);
+
+    // No more ticks for the transmitter
+    vw_tx_enabled = false;
+}
+
+// Enable the receiver. When a message becomes available, vw_rx_done flag
+// is set, and vw_wait_rx() will return.
+void vw_rx_start()
+{
+    if (!vw_rx_enabled)
+    {
+	vw_rx_enabled = true;
+	vw_rx_active = false; // Never restart a partial message
+    }
+}
+
+// Disable the receiver
+void vw_rx_stop()
+{
+    vw_rx_enabled = false;
+}
+
+// Return true if the transmitter is active
+uint8_t vx_tx_active()
+{
+    return vw_tx_enabled;
+}
+
+// Wait for the transmitter to become available
+// Busy-wait loop until the ISR says the message has been sent
+void vw_wait_tx()
+{
+    while (vw_tx_enabled)
+	;
+}
+
+// Wait for the receiver to get a message
+// Busy-wait loop until the ISR says a message is available
+// can then call vw_get_message()
+void vw_wait_rx()
+{
+    while (!vw_rx_done)
+	;
+}
+
+// Wait at most max milliseconds for the receiver to receive a message
+// Return the truth of whether there is a message
+uint8_t vw_wait_rx_max(unsigned long milliseconds)
+{
+    unsigned long start = millis();
+
+    while (!vw_rx_done && ((millis() - start) < milliseconds))
+	;
+    return vw_rx_done;
+}
+
+// Wait until transmitter is available and encode and queue the message
+// into vw_tx_buf
+// The message is raw bytes, with no packet structure imposed
+// It is transmitted preceded a byte count and followed by 2 FCS bytes
+uint8_t vw_send(uint8_t* buf, uint8_t len)
+{
+    uint8_t i;
+    uint8_t index = 0;
+    uint16_t crc = 0xffff;
+    uint8_t *p = vw_tx_buf + VW_HEADER_LEN; // start of the message area
+    uint8_t count = len + 3; // Added byte count and FCS to get total number of bytes
+
+    if (len > VW_MAX_PAYLOAD)
+	return false;
+
+    // Wait for transmitter to become available
+    vw_wait_tx();
+
+    // Encode the message length
+    crc = _crc_ccitt_update(crc, count);
+    p[index++] = symbols[count >> 4];
+    p[index++] = symbols[count & 0xf];
+
+    // Encode the message into 6 bit symbols. Each byte is converted into 
+    // 2 6-bit symbols, high nybble first, low nybble second
+    for (i = 0; i < len; i++)
+    {
+	crc = _crc_ccitt_update(crc, buf[i]);
+	p[index++] = symbols[buf[i] >> 4];
+	p[index++] = symbols[buf[i] & 0xf];
+    }
+
+    // Append the fcs, 16 bits before encoding (4 6-bit symbols after encoding)
+    // Caution: VW expects the _ones_complement_ of the CCITT CRC-16 as the FCS
+    // VW sends FCS as low byte then hi byte
+    crc = ~crc;
+    p[index++] = symbols[(crc >> 4)  & 0xf];
+    p[index++] = symbols[crc & 0xf];
+    p[index++] = symbols[(crc >> 12) & 0xf];
+    p[index++] = symbols[(crc >> 8)  & 0xf];
+
+    // Total number of 6-bit symbols to send
+    vw_tx_len = index + VW_HEADER_LEN;
+
+    // Start the low level interrupt handler sending symbols
+    vw_tx_start();
+
+    return true;
+}
+
+// Return true if there is a message available
+uint8_t vw_have_message()
+{
+    return vw_rx_done;
+}
+
+// Get the last message received (without byte count or FCS)
+// Copy at most *len bytes, set *len to the actual number copied
+// Return true if there is a message and the FCS is OK
+uint8_t vw_get_message(uint8_t* buf, uint8_t* len)
+{
+    uint8_t rxlen;
+    
+    // Message available?
+    if (!vw_rx_done)
+	return false;
+    
+    // Wait until vw_rx_done is set before reading vw_rx_len
+    // then remove bytecount and FCS
+    rxlen = vw_rx_len - 3;
+    
+    // Copy message (good or bad)
+    if (*len > rxlen)
+	*len = rxlen;
+    memcpy(buf, vw_rx_buf + 1, *len);
+    
+    vw_rx_done = false; // OK, got that message thanks
+    
+    // Check the FCS, return goodness
+    return (vw_crc(vw_rx_buf, vw_rx_len) == 0xf0b8); // FCS OK?
+}
+
+// This is the interrupt service routine called when timer1 overflows
+// Its job is to output the next bit from the transmitter (every 8 calls)
+// and to call the PLL code if the receiver is enabled
+//ISR(SIG_OUTPUT_COMPARE1A)
+#if defined (ARDUINO) // Arduino specific
+
+#ifdef __AVR_ATtiny85__
+SIGNAL(TIM0_COMPA_vect)
+#else // Assume Arduino Uno (328p or similar)
+
+SIGNAL(TIMER1_COMPA_vect)
+#endif // __AVR_ATtiny85__
+
+{
+    if (vw_rx_enabled && !vw_tx_enabled)
+	vw_rx_sample = digitalRead(vw_rx_pin);
+    
+    // Do transmitter stuff first to reduce transmitter bit jitter due 
+    // to variable receiver processing
+    if (vw_tx_enabled && vw_tx_sample++ == 0)
+    {
+	// Send next bit
+	// Symbols are sent LSB first
+	// Finished sending the whole message? (after waiting one bit period 
+	// since the last bit)
+	if (vw_tx_index >= vw_tx_len)
+	{
+	    vw_tx_stop();
+	    vw_tx_msg_count++;
+	}
+	else
+	{
+	    digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++));
+	    if (vw_tx_bit >= 6)
+	    {
+		vw_tx_bit = 0;
+		vw_tx_index++;
+	    }
+	}
+    }
+    if (vw_tx_sample > 7)
+	vw_tx_sample = 0;
+    
+    if (vw_rx_enabled && !vw_tx_enabled)
+	vw_pll();
+}
+#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
+void vw_Int_Handler()
+{
+    if (vw_rx_enabled && !vw_tx_enabled)
+	vw_rx_sample = digitalRead(vw_rx_pin);
+    
+    // Do transmitter stuff first to reduce transmitter bit jitter due 
+    // to variable receiver processing
+    if (vw_tx_enabled && vw_tx_sample++ == 0)
+    {
+	// Send next bit
+	// Symbols are sent LSB first
+	// Finished sending the whole message? (after waiting one bit period 
+	// since the last bit)
+	if (vw_tx_index >= vw_tx_len)
+	{
+	    vw_tx_stop();
+	    vw_tx_msg_count++;
+	}
+	else
+	{
+	    digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++));
+	    if (vw_tx_bit >= 6)
+	    {
+		vw_tx_bit = 0;
+		vw_tx_index++;
+	    }
+	}
+    }
+    if (vw_tx_sample > 7)
+	vw_tx_sample = 0;
+    
+    if (vw_rx_enabled && !vw_tx_enabled)
+	vw_pll();
+}
+
+interrupt(TIMER0_A0_VECTOR) Timer_A_int(void) 
+{
+    vw_Int_Handler();
+};
+
+#endif
+
+

+ 301 - 0
VirtualWire.h

@@ -0,0 +1,301 @@
+// VirtualWire.h
+//
+// Virtual Wire implementation for Arduino
+// See the README file in this directory fdor documentation
+// 
+// Author: Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS
+// Copyright (C) 2008 Mike McCauley
+// $Id: VirtualWire.h,v 1.6 2013/02/14 22:02:11 mikem Exp mikem $
+
+#ifndef _UTIL_CRC16_H_
+#define _UTIL_CRC16_H_
+
+#endif /* _UTIL_CRC16_H_ */
+
+
+
+/// \mainpage VirtualWire library for Arduino
+///
+/// This is the Arduino VirtualWire library.
+///
+/// VirtualWire is an Arduino library that provides features to send short
+/// messages, without addressing, retransmit or acknowledgment, a bit like UDP
+/// over wireless, using ASK (amplitude shift keying). Supports a number of
+/// inexpensive radio transmitters and receivers. All that is required is
+/// transmit data, receive data and (for transmitters, optionally) a PTT
+/// transmitter enable.
+///
+/// It is intended to be compatible with the RF Monolithics (www.rfm.com)
+/// Virtual Wire protocol, but this has not been tested.
+///
+/// Does not use the Arduino UART. Messages are sent with a training preamble,
+/// message length and checksum. Messages are sent with 4-to-6 bit encoding
+/// for good DC balance, and a CRC checksum for message integrity.
+///
+/// Why not just use the Arduino UART connected directly to the
+/// transmitter/receiver? As discussed in the RFM documentation, ASK receivers
+/// require a burst of training pulses to synchronize the transmitter and
+/// receiver, and also requires good balance between 0s and 1s in the message
+/// stream in order to maintain the DC balance of the message. UARTs do not
+/// provide these. They work a bit with ASK wireless, but not as well as this
+/// code.
+///
+/// This library provides classes for 
+/// - VirtualWire: unaddressed, unreliable messages
+///
+/// Example Arduino programs are included to show the main modes of use.
+///
+/// The version of the package that this documentation refers to can be downloaded 
+/// from http://www.airspayce.com/mikem/arduino/VirtualWire/VirtualWire-1.15.zip
+/// You can find the latest version at http://www.airspayce.com/mikem/arduino/VirtualWire
+///
+/// You can also find online help and disussion at http://groups.google.com/group/virtualwire
+/// Please use that group for all questions and discussions on this topic. 
+/// Do not contact the author directly, unless it is to discuss commercial licensing.
+///
+/// \par Supported Hardware
+/// A range of communications hardware is supported. The ones listed blow are
+/// available in common retail outlets in Australian and other countries for
+/// under $10 per unit. Many other modules may also work with this software.
+/// Runs on ATmega8/168 (Arduino Diecimila, Uno etc) and ATmega328 and possibly
+/// others. Also runs on on Energia with MSP430G2553 / G2452 and Arduino with 
+/// ATMega328 (courtesy Yannick DEVOS - XV4Y).
+/// Also compiles and runs on ATtiny85 in Arduino environment, courtesy r4z0r7o3.
+///
+/// - Receivers
+///  - RX-B1 (433.92MHz) (also known as ST-RX04-ASK)
+/// - Transmitters: 
+///  - TX-C1 (433.92MHz)
+/// - Transceivers
+///  - DR3100 (433.92MHz)
+///
+/// \par Installation
+/// To install, unzip the library into the libraries sub-directory of your
+/// Arduino application directory. Then launch the Arduino environment; you
+/// should see the library in the Sketch->Import Library menu, and example
+/// code in
+/// File->Sketchbook->Examples->VirtualWire menu.
+///
+/// \par Open Source Licensing GPL V2
+///
+/// This is the appropriate option if you want to share the source code of your
+/// application with everyone you distribute it to, and you also want to give them
+/// the right to share who uses it. If you wish to use this software under Open
+/// Source Licensing, you must contribute all your source code to the open source
+/// community in accordance with the GPL Version 2 when your application is
+/// distributed. See http://www.gnu.org/copyleft/gpl.html
+/// 
+/// \par Commercial Licensing
+///
+/// This is the appropriate option if you are creating proprietary applications
+/// and you are not prepared to distribute and share the source code of your
+/// application. Contact info@airspayce.com for details.
+///
+/// \par Revision History
+/// \version 1.0 Original release
+/// 
+/// \version 1.1 2008-06-24
+/// 	Now can compile for atmega8
+///	Reported by creatrope
+/// \version 1.2 2009-03-30
+///	Fixed a problem that prevented compiling with arduino-0015
+///	Reported by Jaime Castro
+/// \version 1.3 2009-04-01
+///	Fixed a compatibility problem with ATMEGA328 of the new arduino
+///	Now use SIGNAL(TIMER1_COMPA_vect) instead of ISR(SIG_OUTPUT_COMPARE1A)
+///	as discussed in
+///	http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1237714550/11
+///	and reported by Jaime Castro.
+/// \version 1.4 2010-01-29
+///	Added vx_tx_active(), suggested by Alan Burlison.
+/// \version 1.5 2011-09-09
+///	Added vx_tx_active() function.
+/// \version 1.6 2012-01-10
+///	Fixed a problem where the receiver was always reenabled after
+///	transmission. Reported by David Bath
+/// \version 1.9 2012-02-07 Documentation updates
+///	Documentation updates
+/// \version 1.10 Updated CHANGES file with changes since 1.4.
+/// \version 1.11 Converted documentation to Doxygen. Moved CHANGES log to this version history.
+///     Ensure vw_rx_pin is not accessed unless receiver is enabled
+/// \version 1.12 Compiles and runs on on Energia with MSP430G2553 / G2452 and Arduino with ATMega328. 
+///     Patches contributed by Yannick DEVOS - XV4Y
+/// \version 1.13 util/crc16.h needed for compiling on  Energia with MSP430G2553 / G2452 was accidentally
+///     left out of the distribution
+/// \version 1.14 Added support ATtiny85 on Arduino, patch provided by r4z0r7o3.
+/// \version 1.15 Updated author and distribution location details to airspayce.com
+///
+/// \par Implementation Details
+/// See: http://www.airspayce.com/mikem/arduino/VirtualWire.pdf
+///
+/// \par Performance
+/// See: http://www.airspayce.com/mikem/arduino/VirtualWire.pdf
+///
+/// \par Connections
+/// See: http://www.airspayce.com/mikem/arduino/VirtualWire.pdf
+///
+/// \file VirtualWire.h
+/// \brief VirtualWire API
+///
+/// To use the VirtualWire library, you must have
+/// \code
+/// #include <VirtualWire.h>
+/// \endcode
+/// At the top of your sketch.
+/// 
+
+#ifndef VirtualWire_h
+#define VirtualWire_h
+
+#include <stdlib.h>
+#if defined(ARDUINO)
+ #if ARDUINO >= 100
+  #include <Arduino.h>
+ #else
+  #include <wiring.h>
+ #endif
+#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
+ #include "legacymsp430.h"
+ #include "Energia.h"
+#else // error
+ #error Platform not defined
+#endif
+
+
+
+
+// These defs cause trouble on some versions of Arduino
+#undef abs
+#undef double
+#undef round
+
+/// Maximum number of bytes in a message, counting the byte count and FCS
+#define VW_MAX_MESSAGE_LEN 30
+
+/// The maximum payload length
+#define VW_MAX_PAYLOAD VW_MAX_MESSAGE_LEN-3
+
+/// The size of the receiver ramp. Ramp wraps modulu this number
+#define VW_RX_RAMP_LEN 160
+
+/// Number of samples per bit
+#define VW_RX_SAMPLES_PER_BIT 8
+
+// Ramp adjustment parameters
+// Standard is if a transition occurs before VW_RAMP_TRANSITION (80) in the ramp,
+// the ramp is retarded by adding VW_RAMP_INC_RETARD (11)
+// else by adding VW_RAMP_INC_ADVANCE (29)
+// If there is no transition it is adjusted by VW_RAMP_INC (20)
+/// Internal ramp adjustment parameter
+#define VW_RAMP_INC (VW_RX_RAMP_LEN/VW_RX_SAMPLES_PER_BIT)
+/// Internal ramp adjustment parameter
+#define VW_RAMP_TRANSITION VW_RX_RAMP_LEN/2
+/// Internal ramp adjustment parameter
+#define VW_RAMP_ADJUST 9
+/// Internal ramp adjustment parameter
+#define VW_RAMP_INC_RETARD (VW_RAMP_INC-VW_RAMP_ADJUST)
+/// Internal ramp adjustment parameter
+#define VW_RAMP_INC_ADVANCE (VW_RAMP_INC+VW_RAMP_ADJUST)
+
+/// Outgoing message bits grouped as 6-bit words
+/// 36 alternating 1/0 bits, followed by 12 bits of start symbol
+/// Followed immediately by the 4-6 bit encoded byte count, 
+/// message buffer and 2 byte FCS
+/// Each byte from the byte count on is translated into 2x6-bit words
+/// Caution, each symbol is transmitted LSBit first, 
+/// but each byte is transmitted high nybble first
+#define VW_HEADER_LEN 8
+
+// Cant really do this as a real C++ class, since we need to have 
+// an ISR
+
+    /// Set the digital IO pin to be for transmit data. 
+    /// This pin will only be accessed if
+    /// the transmitter is enabled
+    /// \param[in] pin The Arduino pin number for transmitting data. Defaults to 12.
+    extern void vw_set_tx_pin(uint8_t pin);
+
+    /// Set the digital IO pin to be for receive data.
+    /// This pin will only be accessed if
+    /// the receiver is enabled
+    /// \param[in] pin The Arduino pin number for receiving data. Defaults to 11.
+    extern void vw_set_rx_pin(uint8_t pin);
+
+    // Set the digital IO pin to enable the transmitter (press to talk, PTT)'
+    /// This pin will only be accessed if
+    /// the transmitter is enabled
+    /// \param[in] pin The Arduino pin number to enable the transmitter. Defaults to 10.
+    extern void vw_set_ptt_pin(uint8_t pin);
+
+    /// By default the PTT pin goes high when the transmitter is enabled.
+    /// This flag forces it low when the transmitter is enabled.
+    /// \param[in] inverted True to invert PTT
+    extern void vw_set_ptt_inverted(uint8_t inverted);
+
+    /// Initialise the VirtualWire software, to operate at speed bits per second
+    /// Call this one in your setup() after any vw_set_* calls
+    /// Must call vw_rx_start() before you will get any messages
+    /// \param[in] speed Desired speed in bits per second
+    extern void vw_setup(uint16_t speed);
+
+    /// Start the Phase Locked Loop listening to the receiver
+    /// Must do this before you can receive any messages
+    /// When a message is available (good checksum or not), vw_have_message();
+    /// will return true.
+    extern void vw_rx_start();
+
+    /// Stop the Phase Locked Loop listening to the receiver
+    /// No messages will be received until vw_rx_start() is called again
+    /// Saves interrupt processing cycles
+    extern void vw_rx_stop();
+
+    /// Returns the state of the
+    /// transmitter
+    /// \return true if the transmitter is active else false
+    extern uint8_t vx_tx_active();
+
+    /// Block until the transmitter is idle
+    /// then returns
+    extern void vw_wait_tx();
+
+    /// Block until a message is available
+    /// then returns
+    extern void vw_wait_rx();
+
+    /// Block until a message is available or for a max time
+    /// \param[in] milliseconds Maximum time to wait in milliseconds.
+    /// \return true if a message is available, false if the wait timed out.
+    extern uint8_t vw_wait_rx_max(unsigned long milliseconds);
+
+    /// Send a message with the given length. Returns almost immediately,
+    /// and message will be sent at the right timing by interrupts
+    /// \param[in] buf Pointer to the data to transmit
+    /// \param[in] len Number of octetes to transmit
+    /// \return true if the message was accepted for transmission, false if the message is too long (>VW_MAX_MESSAGE_LEN - 3)
+    extern uint8_t vw_send(uint8_t* buf, uint8_t len);
+
+    // Returns true if an unread message is available
+    /// \return true if a message is available to read
+    extern uint8_t vw_have_message();
+
+    // If a message is available (good checksum or not), copies
+    // up to *len octets to buf.
+    /// \param[in] buf Pointer to location to save the read data (must be at least *len bytes.
+    /// \param[in,out] len Available space in buf. Will be set to the actual number of octets read
+    /// \return true if there was a message and the checksum was good
+    extern uint8_t vw_get_message(uint8_t* buf, uint8_t* len);
+
+
+/// @example client.pde
+/// Client side of simple client/server pair using VirtualWire
+
+/// @example server.pde
+/// Server side of simple client/server pair using VirtualWire
+
+/// @example transmitter.pde
+/// Transmitter side of simple one-way transmitter->receiver pair using VirtualWire
+
+/// @example receiver.pde
+/// Transmitter side of simple one-way transmitter->receiver pair using VirtualWire
+
+#endif

+ 420 - 24
backend.c

@@ -1,12 +1,116 @@
 #include "backend.h"
 
 
+
 #include "bus.h"
 #ifdef __linux__
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
 #include "config.h"
+#include "timer.h"
+#include "mount.h"
 int data[3]={0};
 #include "io.h"
 
+typedef struct
+{
+	uint16_t year;
+	uint8_t  month;
+	uint8_t  day;
+} db_date_t;
+
+typedef struct 
+{
+	db_date_t date;
+	off_t index;
+} db_metadata_t;
+
+typedef struct 
+{
+	db_date_t date;
+	uint32_t micros;
+} db_data_t;
+
+static int need_flush=0;
+static pthread_t thread;
+
+
+int init_data_files(config_t* cfg)
+{
+	char file[256];
+	FILE* f = NULL;
+	
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.years"));
+	f=fopen(file, "rb");
+	if(!f)
+	{
+		f=fopen(file, "w+");
+		if(!f)
+		{
+			fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
+			return -1;
+		}
+	}
+	fclose(f);
+	
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.monthes"));
+	f=fopen(file, "rb");
+	if(!f)
+	{
+		f=fopen(file, "w+");
+		if(!f)
+		{
+			fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
+			return -1;
+		}
+	}
+	fclose(f);
+	
+	
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.days"));
+	f=fopen(file, "rb");
+	if(!f)
+	{
+		f=fopen(file, "w+");
+		if(!f)
+		{
+			fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
+			return -1;
+		}
+	}
+	fclose(f);
+	
+	
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.data"));
+	f=fopen(file, "rb");
+	if(!f)
+	{
+		f=fopen(file, "w+");
+		if(!f)
+		{
+			fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
+			return -1;
+		}
+	}
+	fclose(f);
+	
+	sprintf(file, "%s", config_get_string(cfg, "cache.file"));
+	f=fopen(file, "w+");
+	if(!f)
+	{
+		fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
+		return -1;
+	}
+	fclose(f);
+	return 0;
+}
+
 int do_pid_file(config_t* cfg)
 {
 	const char* file = config_get_string(cfg, "misc.pidfile");
@@ -29,40 +133,332 @@ int do_pid_file(config_t* cfg)
 
 
 
-int main_loop()
+
+
+
+void usr1_handler(int signo)
+{
+  if (signo == SIGUSR1)
+  {
+		need_flush=1;
+	}
+}
+
+int backend_init(config_t* cfg, bus_t* bus, const char* config)
 {
-	config_t cfg;
-	bus_t bus;
-	pthread_t thread;
-	FILE* file = NULL;
-	struct timeval tv;
 	time(NULL);
 	setup_io();
-	config_init(&cfg, "config.cfg");
-	config_print(&cfg);
-	bus_init_recv(&bus, config_get_int(&cfg, "pin.data"), 
-											config_get_int(&cfg, "pin.clk"), 
-											config_get_int(&cfg, "pin.ack"));
-	init_read_pin(config_get_int(&cfg, "pin.data"), 
-								config_get_int(&cfg, "pin.clk"), 
-								config_get_int(&cfg, "pin.ack"));
-								
-	pthread_create(&thread, NULL, bus_recv_thread, &bus);
+	config_init(cfg, "config.cfg");
+	config_print(cfg);
+	
+	if(do_pid_file(cfg)) return -1;
+	
+	if(init_data_files(cfg)) return -1;
+	
+	if (signal(SIGUSR1, usr1_handler) == SIG_ERR)
+		fprintf(stderr, "Error unable to catch signal : %s\n", strerror(errno));
+	
+	if(config_get_int(cfg, "mount") && !is_mounted(config_get_string(cfg, "mount.dst")))
+	{
+		if(mount_samba(cfg))
+			return -1;
+	}
+	
+	bus_init_recv(bus, config_get_int(cfg, "pin.data"), 
+											config_get_int(cfg, "pin.clk"), 
+											config_get_int(cfg, "pin.ack"));
+	init_read_pin(config_get_int(cfg, "pin.data"), 
+								config_get_int(cfg, "pin.clk"), 
+								config_get_int(cfg, "pin.ack"));
+	
+	#ifdef ARM
+		pthread_create(&thread, NULL, bus_recv_thread, &bus);
+	#endif
+	return 0;
+}
+
+void get_date(uint64_t time, date_t* date)
+{
+	struct tm t;
+	time_t ti = time;
+	t=*localtime(&ti);
+	date->year = t.tm_year+1900;
+	date->month = t.tm_mon+1;
+	date->day = t.tm_mday;
+	date->sec = t.tm_sec + t.tm_min*60 + t.tm_hour*3600;
+	date->usec = time%1000000;
+}
+
+int insert_index_day(config_t *cfg, db_metadata_t* db)
+{
+	char file[256];
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.days"));
+	FILE* f = fopen(file, "r+");
+	
+	if(!f)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en ecriture : %s\n"
+									, file, strerror(errno));
+		return -1;
+	}
+	fseek(f, 0, SEEK_END);
+	
+	fwrite(db, sizeof(db_metadata_t), 1, f);
+	
+	fclose(f);
+	return 0;
+}
+
+
+int insert_index_month(config_t *cfg, db_metadata_t* _db)
+{
+	char file[256];
+	FILE* f;
+	db_metadata_t db = {0};
+	db.date.year=_db->date.year;
+	db.date.month=_db->date.month;
+	db.index=_db->index;
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.monthes"));
+	f = fopen(file, "r+");
+	
+	if(!f)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en ecriture : %s\n"
+									, file, strerror(errno));
+		return -1;
+	}
+	fseek(f, 0, SEEK_END);
+	
+	fwrite(&db, sizeof(db_metadata_t), 1, f);
+	
+	fclose(f);
+	return 0;
+}
+
+
+int insert_index_year(config_t *cfg, db_metadata_t* _db)
+{
+	char file[256];
+	FILE* f;
+	db_metadata_t db = {0};
+	db.date.year=_db->date.year;
+	db.index=_db->index;
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.years"));
+	f = fopen(file, "r+");
+	
+	if(!f)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en ecriture : %s\n"
+									, file, strerror(errno));
+		return -1;
+	}
+	fseek(f, 0, SEEK_END);
+	
+	fwrite(&db, sizeof(db_metadata_t), 1, f);
+	
+	fclose(f);
+	return 0;
+}
+
+int get_last_index_date(config_t* cfg, db_data_t* md, off_t* iy, off_t* im, off_t* id)
+{
+	FILE* f;
+	char file[256];
+	
+	md->micros=0;
+	md->date.year=md->date.month=md->date.day=0;
+	
+	
+	//data
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.data"));
+	f=fopen(file, "rb");
+	if(!f)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
+									, file, strerror(errno));
+		return -1;
+	}
+	fseek(f, -sizeof(db_data_t), SEEK_END);
+	fread(md, sizeof(db_data_t), 1, f);
+	fclose(f);
+	
+	
+	//index Year
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.years"));
+	f=fopen(file, "rb");
+	if(!f)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
+									, file, strerror(errno));
+		return -1;
+	}
+	fseek(f, 0, SEEK_END);
+	*im = ftell(f) / sizeof(db_metadata_t);
+	fclose(f);
+	
+	//index month
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.monthes"));
+	f=fopen(file, "rb");
+	if(!f)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
+									, file, strerror(errno));
+		return -1;
+	}
+	fseek(f,0, SEEK_END);
+	*im = ftell(f) / sizeof(db_metadata_t);
+	fclose(f);
+	
+	//index day
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.days"));
+	f=fopen(file, "rb");
+	if(!f)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
+									, file, strerror(errno));
+		return -1;
+	}
+	fseek(f, 0, SEEK_END);
+	*id = ftell(f) / sizeof(db_metadata_t);
+	fclose(f);
+	
+	return 0;
+}
+
+int backend_flush(config_t* cfg)
+{
+	db_data_t curr, last;
+	off_t indexY, indexM, indexDay, indexData;
+	char file[256];
+	sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
+												 config_get_string(cfg, "storage.data"));
+	
+	get_last_index_date(cfg, &last, &indexY, &indexM, &indexDay);
+	
+	FILE* f = fopen(file, "wb");
+	if(!f)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
+									, file, strerror(errno));
+		return -1;
+	}
+	fseek(f, 0, SEEK_END);
+	indexData=ftell(f)/sizeof(db_data_t);
+	
+	
+	FILE* in = fopen(config_get_string(cfg, "cache.file"), "rb");
+	if(!in)
+	{
+		fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
+									, config_get_string(cfg, "cache.file"), strerror(errno));
+		return -1;
+	}
+	while( (fread(&curr, sizeof(db_data_t), 1, in))>0 )
+	{
+		if(curr.date.day != last.date.day)
+		{
+			db_metadata_t t={0};
+			t.date=curr.date;
+			t.index=indexData;
+			indexDay++;
+			insert_index_day(cfg, &t);
+			last.date.day=curr.date.day;
+		}
+		if(curr.date.month != last.date.month)
+		{			
+			db_metadata_t t={0};
+			t.date.year=curr.date.year;
+			t.date.month=curr.date.month;
+			t.index=indexDay-1;
+			indexM++;
+			insert_index_month(cfg, &t);
+			last.date.month=curr.date.month;
+		}
+		if(curr.date.year != last.date.year)
+		{
+			db_metadata_t t={0};
+			t.date.year=curr.date.year;
+			t.index=indexM-1;
+			indexY++;
+			insert_index_year(cfg, &t);
+			last.date.year=curr.date.year;
+		}
+		
+		fwrite(&curr, sizeof(db_data_t), 1, f);
+		
+		indexData++;
+	}
+	fprintf(stderr, "Sortie: %s\n", strerror(errno) );
+	fclose(f);
+	fclose(in);
+	
+	f = fopen(config_get_string(cfg, "cache.file"), "w+");
+	fclose(f);
+	
+	return 0;
+	
+	
+}
+
+void backend_insert(config_t* cfg, uint64_t c)
+{
+	db_data_t d;
+	date_t dd; 
+	FILE* f = fopen(config_get_string(cfg, "cache.file"), "r+");
+	if(!f)
+	{
+		fprintf(stderr, "Cant open cache file '%s' : %s\n", config_get_string(cfg, "cache.file"), strerror(errno));
+		return;
+	}
+	get_date(c, &dd);
+	d.date.year=dd.year;
+	d.date.month=dd.month;
+	d.date.day=dd.day;
+	d.micros=dd.sec*1000 + dd.usec/1000;
+	//printf("Insert: %d-%d-%d : %d:%d:%d.%d \n", dd.year, dd.month, dd.day, d.micros/3600000, (d.micros%3600000)/60000, d.micros%60000/1000, d.micros%1000);
+	fseek(f, 0, SEEK_END);
+	
+	fwrite(&d, sizeof(db_data_t), 1, f);
+	fclose(f);
+}
+
+
+
+
+void backend_loop(config_t* cfg, bus_t* bus)
+{
+	uint64_t interval = config_get_int(cfg, "cache.flush_interval");
+	uint64_t last_flush = get_time_us()/1000000, current;
+	int i=0, n=(28*12*2)*100;
 	while(1)
 	{
 		uint32_t c;
-		double w;
-		char buffer[16];
-		bus_read(&bus, &c, 4);
 		
+		current=get_time_us()/1000000;
+		if(current>= interval +last_flush || need_flush || i==n)
+		{
+			printf("Flushing\n");
+			last_flush=current;
+			backend_flush(cfg);
+			need_flush=0;
+			if(i==n) return;
+		}
+		
+	
 		
-		printf("%ld' s  %ld ms %'d us \n", c/1000000, c%1000000/1000, c%1000);
-		w=3600.0/(((double)c)/1000000.0);
-		printf("\t%.2lf W %.2lf A\n\n", w, w/220);
+		bus_read(bus, &c, 4);
+		backend_insert(cfg, c);
+		i++;
 	}
 
-
+	return;
 }
 
-
 #endif

+ 1 - 0
backend.h

@@ -10,6 +10,7 @@
 
 
 #include "bus.h"
+#include "config.h"
 
 int do_pid_file(config_t* cfg);
 int main_loop();

+ 37 - 5
bus.c

@@ -1,6 +1,12 @@
 #include "bus.h"
 #include "timer.h"
 #include "io.h"
+#include <time.h>
+
+#ifdef __linux__
+	#include <sys/time.h>
+#endif
+
 void file_produce(file_t* f, char x)
 {
 	f->buffer[f->t]=x;
@@ -111,6 +117,35 @@ void bus_write(bus_t* bus, const void* x, int length)
 		file_produce(&bus->buffer, iter[i]);
 }
 
+time_t next_time()
+{
+	char buffer[512];
+	static int y=2016, m=5 , d=1, h=0;
+	struct tm t={0};
+	t.tm_year=y-1900;
+	t.tm_mon=m-1;
+	t.tm_mday=d;
+	t.tm_hour=h;
+	h+=12;
+	if(h==24)
+	{
+		h=0;
+		d++;
+	}
+	if(d>28)
+	{
+		d=1;
+		m++;
+	}
+	
+	if(m>12)
+	{
+		m=1;
+		y++;
+	}
+	return mktime(&t);
+}
+
 void bus_read(bus_t* bus, void* x, int length)
 {
 	#ifdef __linux__
@@ -121,13 +156,10 @@ void bus_read(bus_t* bus, void* x, int length)
 			for(i=0; i<length; i++)
 				iter[i]=file_consume(&bus->buffer);
 		#else
-			static uint64_t old=0;
-			int i;
 			struct timeval tv;
-			sleep(1);
+			usleep(100);
 			gettimeofday(&tv, NULL);
-			*(uint32_t*)x=(tv.tv_sec-old)*1000000;
-			old=tv.tv_sec;
+			*(uint32_t*)x=next_time();
 		#endif
 	#endif
 }

+ 4 - 4
config.c

@@ -5,8 +5,8 @@ void config_load_default(config_t *cfg)
 	config_add_int(cfg, "pin.data", 2); 
 	config_add_int(cfg, "pin.clk", 3); 
 	config_add_int(cfg, "pin.ack", 4);
-	config_add_int(cfg, "cache.size", 4096);
-
+	
+	config_add_int(cfg, "cache.flush_interval", 86400);
 	config_add_string(cfg, "cache.file", "/tmp/compteur_elec.cache");
 	
 	config_add_int(cfg, "mount", 1);
@@ -99,7 +99,7 @@ int _config_next_opt(config_t *cfg, FILE* f)
 		char buffer[128];
 		int isfloat=0;
 		buffer[0]=c;
-		for(i=1; (c=_fgetc(cfg, f))>='0' && c<='9' || c=='.' ; i++)
+		for(i=1; ((c=_fgetc(cfg, f))>='0' && c<='9') || c=='.' ; i++)
 		{
 			if(c=='.') isfloat=1;
 			buffer[i]=c;
@@ -177,7 +177,7 @@ void config_add(config_t* cfg, const char* name, int type,  union opt_value val)
 	opt.type=type;
 	opt.val = val;
 	
-	if(o=_config_get(cfg, name))
+	if( (o=_config_get(cfg, name)) )
 		*o=opt;
 	else cfg->opts[cfg->n++]=opt;
 }

+ 8 - 7
config.cfg

@@ -4,23 +4,24 @@ pin.clk = 3;
 pin.ack= 4;
 
 #cache
-cache.size =2048;
+#en secondes
+cache.flush_interval = 86400; # 1 journee
 cache.file="/tmp/compteur_elec.cache";
 
 #Samba mount
 mount=1;
-mount.ip="192.168.0.88";
-mount.src="//192.168.0.88/nas";
+mount.ip="192.168.1.2";
+mount.src="//192.168.1.2/Partage coloc/fanch/compteur";
 mount.dst="/media/samba";
-mount.username="ptitcois";
-mount.password="e1010898";
+mount.username="re";
+mount.password="mi";
 
 #storage
-storage.location="/media/samba";
+storage.location="/media/test";
 storage.data="data";
 storage.years="years";
 storage.monthes="monthes";
 storage.days="days";
 
 
-misc.pidfile="/tmp/compteur_elec.cache";
+misc.pidfile="/tmp/compteur_elec.pid";

+ 7 - 8
io.h

@@ -13,7 +13,7 @@
 	#include <time.h>
 	#include <fcntl.h>
 	#include <pthread.h>
-	//#define ARM 1
+	#define ARM 1
 	#define BCM2708_PERI_BASE        0x20000000
 	#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
  
@@ -31,22 +31,21 @@
 	extern int  mem_fd;
 	extern void *gpio_map;
 	 
-	// I/O access
+	/* I/O access */
 	extern volatile unsigned *gpio;
 	 
-	// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
 	#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
 	#define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
 	#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
 	 
-	#define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
-	#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
+	#define GPIO_SET *(gpio+7)  
+	#define GPIO_CLR *(gpio+10) 
 	#define GPIO_WRITE(gpio, value) ((value)?(GPIO_SET = 1 << gpio):(GPIO_CLR = 1 << gpio)) 
 	 
-	#define GET_GPIO(g) ((*(gpio+13)&(1<<g))?1:0) // 0 if LOW, (1<<g) if HIGH
+	#define GET_GPIO(g) ((*(gpio+13)&(1<<g))?1:0) 
 	 
-	#define GPIO_PULL *(gpio+37) // Pull up/pull down
-	#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
+	#define GPIO_PULL *(gpio+37) 
+	#define GPIO_PULLCLK0 *(gpio+38) 
 	void setup_io();
 #else
 	#include <Arduino.h>

+ 2 - 4
mount.c

@@ -21,6 +21,7 @@ int next_word(FILE* f, char* out)
 	if(c=='\n') return 1;
 	if(c==' ' || c=='\t') return 0;
 	if(c==EOF) return -1;
+	return 0;
 }
 
 int is_mounted(const char* mp)
@@ -47,14 +48,11 @@ int is_mounted(const char* mp)
 		while((c=next_word(f, buf))==0);
 	}
 	
-	
-	
 	fclose(f);
 	return 0;
 }
 
 
-
 int mount_samba(config_t* cfg)
 {
 	int tomount=config_get_int(cfg, "mount");
@@ -67,7 +65,7 @@ int mount_samba(config_t* cfg)
 	
 	if(!tomount) return 0;
 	
-	sprintf(buffer, "unc=%s,ip=%s,username=%s,password=%s", src, ip, username, password); 
+	sprintf(buffer, "unc='%s',ip=%s,username=%s,password=%s", src, ip, username, password); 
 	printf("%s\n", buffer);
 	
 	if(mount(src, dst, "cifs", MS_MGC_VAL | MS_SILENT, buffer))

+ 9 - 9
recv.c

@@ -2,20 +2,20 @@
 #include "config.h"
 #include "mount.h"
 
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+
 
 
 int main()
 {
-	config_t c;
-	printf("/ : %d\n\n", is_mounted("/"));
-	printf("/home : %d\n\n", is_mounted("/home"));
-	printf("/existepas : %d\n\n", is_mounted("/existepas"));
-	printf("/dev : %d\n\n", is_mounted("/dev"));
-	config_init(&c, "config.cfg");
+	config_t cfg;
+	bus_t bus;
 	
-	mount_samba(&c);
-
+	backend_init(&cfg, &bus, "config.cfg");
+	backend_loop(&cfg, &bus);
 	
-	config_free(&c);
+	config_free(&cfg);
 	//main_loop();
 }

+ 50 - 0
send.c

@@ -28,8 +28,34 @@
 	}
 #endif
 
+
+#include "VirtualWire.h"
+void init_rf()
+{
+		//vw_set_tx_pin(transmit_pin);
+    vw_set_rx_pin(0);
+    //vw_set_ptt_pin(transmit_en_pin);
+    vw_set_ptt_inverted(true); // Required for DR3100
+    vw_setup(2000);       // Bits per sec
+    //pinMode(led_pin, OUTPUT);
+}
+
+void send_sync(void* data, int length)
+{
+	vw_send((uint8_t *)data, length);
+  vw_wait_tx();
+}
+
+
+const int led_pin = 11;
+const int transmit_pin = 0;
+const int receive_pin = 2;
+const int transmit_en_pin = 3;
+
+int count = 1;
 int main()
 {
+	/*
 	unsigned long last=0;
 	unsigned long current_data = 0;
 	bus_t bus;
@@ -49,6 +75,30 @@ int main()
 		last=micros();
 		bus_write_sync(&bus, &current_data, 4);
 	}
+	*
+	char salut[10] = "Salut   ";
+	init_rf();
+	salut[7]=3;
+	salut[8]=4;
+	salut[9]=5;
+	send_sync(salut, 10);*/
+	vw_set_tx_pin(transmit_pin);
+    vw_set_rx_pin(receive_pin);
+    vw_set_ptt_pin(transmit_en_pin);
+    vw_set_ptt_inverted(true); // Required for DR3100
+    vw_setup(2000);       // Bits per sec
+    pinMode(led_pin, OUTPUT);
+	
+	
+	 char msg[7] = {'h','e','l','l','o',' ','#'};
+
+  msg[6] = count;
+  digitalWrite(led_pin, HIGH); // Flash a light to show transmitting
+  vw_send((uint8_t *)msg, 7);
+  vw_wait_tx(); // Wait until the whole message is gone
+  digitalWrite(led_pin, LOW);
+  delay(1000);
+  count = count + 1;
 }
 
 

+ 2 - 1
server/db.c

@@ -180,6 +180,7 @@ db_data_set_t* db_get(db_t* db, db_time_t* start, db_time_t* end)
 	return NULL;
 }
 
+/*
 int main(int argc, char** argv)
 {
 	cache_t cache;
@@ -188,6 +189,6 @@ int main(int argc, char** argv)
 	
 	cache_free(&cache);
 }
-
+*/
 
 

+ 23 - 8
server/db_access.c

@@ -267,7 +267,7 @@ void write_year()
 
 
 
-db_data_interval_t* db_load_fault(db_t* db, db_date_t ds, uint32_t dsm,
+db_data_interval_t* db_data_load(db_t* db, db_date_t ds, uint32_t dsm,
 																							db_date_t de, uint32_t dem)
 {
 	int f;
@@ -306,13 +306,13 @@ db_data_interval_t* db_load_fault(db_t* db, db_date_t ds, uint32_t dsm,
 }
 
 
-/*
+
 int main(int argc, char** argv)
 {
-	write_data();
+/*	write_data();
 	write_day();
 	write_month();
-	write_year();
+	write_year();*/
 	db_t db;
 	db_data_interval_t *di;
 	db_date_t ds, de;
@@ -337,7 +337,7 @@ int main(int argc, char** argv)
 	
 	
 	int a,m,j,ms;
-	for(a=2015; a<2021; a++)
+	/*for(a=2015; a<2021; a++)
 	{
 		printf("year: %d\n", a);
 		ds.year=a;
@@ -361,7 +361,10 @@ int main(int argc, char** argv)
 						fprintf(stderr , "Error on (%.2d-%.2d-%.2d : %d)\n", j, m ,a ,ms/1000);
 					}
 					else free(di->data);
-				} 
+				}
+				di=db_data_load(&db, ds, dsm, ds, dsm);
+				int l;
+				
 				
 				di=db_data_load(&db, ds, dsm, de, dsm);
 				if(!di)
@@ -372,8 +375,20 @@ int main(int argc, char** argv)
 				
 			}
 		}
-	}
+	}*/
+	ds.year=2016;
+	de.year=ds.year;
+	ds.month=5;
+	de.month=ds.month;
+	ds.day=15;
+	de.day=ds.day+1;
+	dsm=1000*3600*24;
+	int l;
+	di=db_data_load(&db, ds, 3600*24*100, de, 1);
+	for(l=0; l<di->len; l++)
+					printf("\t\t%d-%d-%d %d:%d:%d.%d\n", di->data[l].date.day, di->data[l].date.month, di->data[l].date.year,
+																								di->data[l].micros/3600000, (di->data[l].micros%3600000)/60000, di->data[l].micros%60000/1000, di->data[l].micros%1000);
 	db_free(&db);
 	
 	return 0;
-}*/
+}

+ 1 - 2
stub.c

@@ -60,7 +60,7 @@ void write_pin(int pin, int value)
 	#ifdef __linux__
 		#ifndef ARM
 			char c = (value)?'1':'0';
-			write(fifos[pin], &c, 1);	
+			//write(fifos[pin], &c, 1);	
 		#else
 			GPIO_WRITE(pin, value);
 		#endif
@@ -73,7 +73,6 @@ int read_pin(int pin)
 {
 	#ifdef __linux__
 		#ifndef ARM
-			int f = fifos[pin];
 			int c=0;
 			while(read(fifos[pin], &c,1)<=0)usleep(10);
 			return (c=='0')?0:1;

+ 0 - 1
timer.c

@@ -2,7 +2,6 @@
 #include "io.h"
 
 
-
 static uint64_t __time_us;
 static uint64_t __delta_time_us;
 

+ 11 - 0
timer.h

@@ -7,6 +7,17 @@
 	#include <time.h>
 #endif
 
+
+
+typedef struct
+{
+	uint8_t day;
+	uint8_t month;
+	uint16_t year;
+	uint32_t sec;
+	uint32_t usec;
+} date_t;
+
 void 			timer_init();
 uint64_t 	get_time_us();
 void 			set_delta();