User Tools

Site Tools


onewire:crc

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
onewire:crc [2012/05/15 13:07] – created fdconewire:crc [2013/09/18 09:08] (current) sdolt
Line 1: Line 1:
 <note>Les exemples pratiques utilisés dans cette démonstration proviennent de [[http://www.maxim-ic.com/app-notes/index.mvp/id/27|cette page]]. </note> <note>Les exemples pratiques utilisés dans cette démonstration proviennent de [[http://www.maxim-ic.com/app-notes/index.mvp/id/27|cette page]]. </note>
 +
 +<note>Sur processeur AVR, une bibliothèque existe : [[avr:crc16.h|Somme de contrôle CRC]]</note>
  
 ====== DOW CRC (Dallas One Wire CRC) ====== ====== DOW CRC (Dallas One Wire CRC) ======
 +<note warning>Le code ci-dessous ne fonctionne pas. Mélange entre chaine de caractère et chaine normale</note>
  
 ===== DOW CRC-8 ===== ===== DOW CRC-8 =====
Line 9: Line 12:
 <file c> <file c>
 #include <stdio.h> #include <stdio.h>
 +#include <string.h>
 #define CRCPOLY8 0x18           //correspond au masque des XOR sur le polynôme x⁸+x⁵+x⁴+x⁰ #define CRCPOLY8 0x18           //correspond au masque des XOR sur le polynôme x⁸+x⁵+x⁴+x⁰
  
-int main(void)+void main(void)
 { {
-        int crc = 0x00 , i = 0, bit_counter = 0, b = 0, feedback_bit = 0;       //déclaration + initialisation des variables+        int crc = 0x00 , i = 0, bit_counter = 0, b = 0, feedback_bit = 0, length = 0;       //déclaration + initialisation des variables
         char string[]={"A200000001B81C02"};     //chaîne utilisée pour le calcul du crc         char string[]={"A200000001B81C02"};     //chaîne utilisée pour le calcul du crc
  
-        for (i=0; i<=15; i++)           //passage dans chaque cellules de la chaine string+        length = strlen(string)-1;          //la longueur de la chaîne -1 (car tableau de caractères commence à 0) 
 +        for (i=0; i<=length; i++)           //passage dans chaque cellules de la chaine string
         {                                {                       
-                b = string[15-i];         //nous travaillons de droite à gauche(15-i)+                b = string[length-i];         //nous travaillons de droite à gauche(length-i)
                 bit_counter = 4;        //si le caractère a déjà été décomposé en hexadécimal => 4 bits par valeur                 bit_counter = 4;        //si le caractère a déjà été décomposé en hexadécimal => 4 bits par valeur
                 while (bit_counter>0)   //passage dans la boucle 4 fois                 while (bit_counter>0)   //passage dans la boucle 4 fois
Line 25: Line 30:
                         if (feedback_bit == 0x01) crc = crc ^ CRCPOLY8;    //si le dernier bit est un 1, XOR entre le CRC et le polynôme                         if (feedback_bit == 0x01) crc = crc ^ CRCPOLY8;    //si le dernier bit est un 1, XOR entre le CRC et le polynôme
                         crc = (crc >> 1) & 0x7F;                        //déplacement de crc de 1 sur la droite + vérification que le bit rajouter (celui de gauche) est bien un 0                         crc = (crc >> 1) & 0x7F;                        //déplacement de crc de 1 sur la droite + vérification que le bit rajouter (celui de gauche) est bien un 0
-                        if (feedback_bit == 0x01) crc = crc | 0x80;      //implantation du 1 du feedback_bit (1 au dernier bit) dans le crc en tant que premier bit+                        if (feedback_bit == 0x01) crc = crc | 0x80;      //implantation du 1 du feedback_bit (1 au dernier bit) dans le crc en tant que premier bit (tout à gauche)
                         b = b>>1;         //déplacement de b de 1 sur la droite (car le dernier bit a déjà été utilisé)                         b = b>>1;         //déplacement de b de 1 sur la droite (car le dernier bit a déjà été utilisé)
                         bit_counter--;                         bit_counter--;
                 }                 }
         }         }
-        printf("0x%i%i\n",crc/16,crc%16)+        printf("%#x\n",crc);
-        return crc;+
 } }
  
 </file> </file>
 ==== Exemple de fonctionnement ==== ==== Exemple de fonctionnement ====
-1-Wire ROM: A2 00 00 00 01 B8 1C 02 \\ CRCPOLY8 = 0x18+1-Wire ROM: A2 00 00 00 01 B8 1C 02 \\ CRCPOLY8 = 0x18 \\ CRCinitial = 0x00
 === i=0 === === i=0 ===
 === b = string [15] <=> '2' [0000'0010] === === b = string [15] <=> '2' [0000'0010] ===
Line 406: Line 410:
 === i=2 === === i=2 ===
 === b = string [13] <=> 'C' [0000'1100] === === b = string [13] <=> 'C' [0000'1100] ===
 +
 +. \\ . \\ .
 +
 +=== i=13 ===
 +=== b = string [2] <=> '0' [0000'0000] ===
 +
 +. \\ . \\ .
 +
 +== bit_counter = 1 ==
 +
 +<code c> feedback_bit = (crc ^ b) & 0x01;</code>
 +^  crc XOR b  ^^
 +|  crc  |  0101'1101  |
 +|  b  |  0000'0000  |
 +^ Résultat |  0101'1101  |
 +
 +^  (crc XOR b) & 0x01  ^^
 +|crc XOR b  |  0101'1101  |
 +|  0x01  |  0000'0001  |
 +^  Résultat  |  0000'0001  |
 +
 +**=> feedback_bit = 0x01**
 +
 +<code c> if (feedback_bit == 0x01) crc = crc ^ CRCPOLY8; </code>
 +
 +^  crc XOR CRCPOLY8  ^^
 +|  crc  |  0101'1101  |
 +|  CRCPOLY8  |  0001'1000  |
 +^  Résultat  |  0100'0101  |
 +
 +**=> crc = 0x45**
 +
 +<code c> crc = (crc >> 1) & 0x7F; </code>
 +
 +^  crc>> ^^
 +|  crc  |  0100'0101  |
 +^  crc>> |  0010'0010  |
 +
 +^  (crc>>1) & 0x7F  ^^
 +|  crc>> |  0010'0010  |
 +|  0x7F  |  0111'1111  |
 +^ Résultat  |  0010'0010  |
 +
 +**=> crc = 0x22**
 +
 +<code c> if (feedback_bit == 0x01) crc = crc | 0x80; </code>
 +
 +^  crc OR 0x80  ^^
 +|  crc  |  0010'0010  |
 +|  0x80  |  1000'0000  |
 +^  Résultat  |  1010'0010  |
 +
 +**=> crc = 0xA2 {C'est la valeur du CRC pour [00000001B81C (Numéro de série) + 02 (Family Code)], s'il est ajouté à la suite du numéro de série, le CRC final sera de 0x00!}**
 +
 +. \\ . \\ .
 +
 +=== i=14 ===
 +=== b = string [1] <=> '2' [0000'0010] ===
  
 . \\ . \\ . . \\ . \\ .
Line 418: Line 480:
 . \\ . \\ . . \\ . \\ .
  
-**=> crc = 0x00**+**=> crc = 0x00 {Nous avons au final un 0x00, 0xA2 est bel et bien le CRC de [00000001B81C02]}** 
 + 
 +===== DOW CRC-16 ===== 
 + 
 +==== Fonction ==== 
 + 
 +<file c> 
 +#include <stdio.h> 
 +#include <string.h> 
 +#define CRCPOLY16 0x4002           //correspond au masque des XOR sur le polynôme x^16+x^15+x^2+x^0 
 + 
 +void main(void) 
 +
 +        int crc = 0x0000 , i = 0, bit_counter = 0, b = 0, feedback_bit = 0, length = 0;       //déclaration + initialisation des variables 
 +        char string[]={"75"};     //chaîne utilisée pour le calcul du crc 
 + 
 +        length = strlen(string)-1;          //la longueur de la chaîne -1 (car tableau de caractères commence à 0) 
 +        for (i=0; i<=length; i++)           //passage dans chaque cellules de la chaine string 
 +        {                        
 +                b = string[length-i];         //nous travaillons de droite à gauche(length-i) 
 +                bit_counter = 4;        //si le caractère a déjà été décomposé en hexadécimal => 4 bits par valeur 
 +                while (bit_counter>0)   //passage dans la boucle 4 fois 
 +                {                                
 +                        feedback_bit = (crc ^ b) & 0x0001;                //vérification de la valeur du dernier bit 
 +                        if (feedback_bit == 0x0001) crc = crc ^ CRCPOLY16;    //si le dernier bit est un 1, XOR entre le CRC et le polynôme 
 +                        crc = (crc >> 1) & 0x7FFF;                        //déplacement de crc de 1 sur la droite + vérification que le bit rajouter (celui de gauche) est bien un 0 
 +                        if (feedback_bit == 0x0001) crc = crc | 0x8000;      //implantation du 1 du feedback_bit (1 au dernier bit) dans le crc en tant que premier bit (tout à gauche) 
 +                        b = b>>1;         //déplacement de b de 1 sur la droite (car le dernier bit a déjà été utilisé) 
 +                        bit_counter--; 
 +                } 
 +        } 
 +        printf("%#x\n",crc); 
 +
 +</file> 
 + 
 +==== Exemple de fonctionnement ==== 
 +1-Wire ROM: 75 \\ CRCPOLY16 = 0x4002 \\ CRCinitial = 0x90F1 
 +=== i=0 === 
 +=== b = string [1] <=> '5' [0000'0000'0000'0101] === 
 + 
 +== bit_counter = 4 == 
 + 
 +<code c> feedback_bit = (crc ^ b) & 0x0001;</code> 
 +^  crc XOR b  ^^ 
 +|  crc  |  1001'0000'1111'0001 
 +|  b  |  0000'0000'0000'0101 
 +^ Résultat |  1001'0000'1111'0100 
 + 
 +^  (crc XOR b) & 0x0001  ^^ 
 +|crc XOR b  |  1001'0000'1111'0100 
 +|  0x0001  |  0000'0000'0000'0001 
 +^  Résultat  |  0000'0000'0000'0000 
 + 
 +**=> feedback_bit = 0x0000** 
 + 
 +<code c> crc = (crc >> 1) & 0x7FFF; </code> 
 + 
 +^  crc>> ^^ 
 +|  crc  |  1001'0000'1111'0001 
 +^  crc>> |  0100'1000'0111'1000 
 + 
 +^  (crc>>1) & 0x7FFF  ^^ 
 +|  crc>> |  0100'1000'0111'1000 
 +|  0x7FFF  |  0111'1111'1111'1111 
 +^ Résultat  |  0100'1000'0111'1000 
 + 
 +**=> crc = 0x4878** 
 + 
 +<code c> b = b>>1; </code> 
 + 
 +^  b>> ^^ 
 +|  b  |  0000'0000'0000'0101 
 +^  b>> |  0000'0000'0000'0010 
 + 
 +**=> b = 0x0002** 
 + 
 +== bit_counter = 3 == 
 + 
 +<code c> feedback_bit = (crc ^ b) & 0x0001;</code> 
 +^  crc XOR b  ^^ 
 +|  crc  |  0100'1000'0111'1000 
 +|  b  |  0000'0000'0000'0010 
 +^ Résultat |  0100'1000'0111'1010 
 + 
 +^  (crc XOR b) & 0x0001  ^^ 
 +|crc XOR b  |  0100'1000'0111'1010 
 +|  0x0001  |  0000'0000'0000'0001 
 +^  Résultat  |  0000'0000'0000'0000 
 + 
 +**=> feedback_bit = 0x0000** 
 + 
 +<code c> crc = (crc >> 1) & 0x7FFF; </code> 
 + 
 +^  crc>> ^^ 
 +|  crc  |  0100'1000'0111'1000 
 +^  crc>> |  0010'0100'0011'1100 
 + 
 +^  (crc>>1) & 0x7FFF  ^^ 
 +|  crc>> |  0010'0100'0011'1100 
 +|  0x7FFF  |  0111'1111'1111'1111 
 +^ Résultat  |  0010'0100'0011'1100 
 + 
 +**=> crc = 0x243C** 
 + 
 +<code c> b = b>>1; </code> 
 + 
 +^  b>> ^^ 
 +|  b  |  0000'0000'0000'0010 
 +^  b>> |  0000'0000'0000'0001 
 + 
 +**=> b = 0x0001** 
 + 
 +== bit_counter = 2 == 
 + 
 +<code c> feedback_bit = (crc ^ b) & 0x0001;</code> 
 +^  crc XOR b  ^^ 
 +|  crc  |  0010'0100'0011'1100 
 +|  b  |  0000'0000'0000'0001 
 +^ Résultat |  0010'0100'0011'1101 
 + 
 +^  (crc XOR b) & 0x0001  ^^ 
 +|crc XOR b  |  0010'0100'0011'1101 
 +|  0x0001  |  0000'0000'0000'0001 
 +^  Résultat  |  0000'0000'0000'0001 
 + 
 +**=> feedback_bit = 0x0001** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc ^ CRCPOLY16; </code> 
 + 
 +^  crc XOR CRCPOLY8  ^^ 
 +|  crc  |  0010'0100'0011'1100 
 +|  CRCPOLY16  |  0100'0000'0000'0010 
 +^  Résultat  |  0110'0100'0011'1110 
 + 
 +**=> crc = 0x643E** 
 + 
 +<code c> crc = (crc >> 1) & 0x7FFF; </code> 
 + 
 +^  crc>> ^^ 
 +|  crc  |  0110'0100'0011'1110 
 +^  crc>> |  0011'0010'0001'1111 
 + 
 +^  (crc>>1) & 0x7FFF  ^^ 
 +|  crc>> |  0011'0010'0001'1111 
 +|  0x7FFF  |  0111'1111'1111'1111 
 +^ Résultat  |  0011'0010'0001'1111 
 + 
 +**=> crc = 0x321F** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc | 0x80; </code> 
 + 
 +^  crc OR 0x8000  ^^ 
 +|  crc  |  0011'0010'0001'1111 
 +|  0x8000  |  1000'0000'0000'0000 
 +^  Résultat  |  1011'0010'0001'1111 
 + 
 +**=> crc = 0xB21F** 
 + 
 +<code c> b = b>>1; </code> 
 + 
 +^  b>> ^^ 
 +|  b  |  0000'0000'0000'0001 
 +^  b>> |  0000'0000'0000'0000 
 + 
 +**=> b = 0x0000** 
 + 
 +== bit_counter = 1 == 
 + 
 +<code c> feedback_bit = (crc ^ b) & 0x0001;</code> 
 +^  crc XOR b  ^^ 
 +|  crc  |  1011'0010'0001'1111 
 +|  b  |  0000'0000'0000'0000 
 +^ Résultat |  1011'0010'0001'1111 
 + 
 +^  (crc XOR b) & 0x0001  ^^ 
 +|crc XOR b  |  1011'0010'0001'1111 
 +|  0x0001  |  0000'0000'0000'0001 
 +^  Résultat  |  0000'0000'0000'0001 
 + 
 +**=> feedback_bit = 0x0001** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc ^ CRCPOLY16; </code> 
 + 
 +^  crc XOR CRCPOLY8  ^^ 
 +|  crc  |  1011'0010'0001'1111 
 +|  CRCPOLY16  |  0100'0000'0000'0010 
 +^  Résultat  |  1111'0010'0001'1101 
 + 
 +**=> crc = 0xF21D** 
 + 
 +<code c> crc = (crc >> 1) & 0x7FFF; </code> 
 + 
 +^  crc>> ^^ 
 +|  crc  |  1111'0010'0001'1101 
 +^  crc>> |  0111'1001'0000'1110 
 + 
 +^  (crc>>1) & 0x7FFF  ^^ 
 +|  crc>> |  0111'1001'0000'1110 
 +|  0x7FFF  |  0111'1111'1111'1111 
 +^ Résultat  |  0111'1001'0000'1110 
 + 
 +**=> crc = 0x790E** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc | 0x80; </code> 
 + 
 +^  crc OR 0x8000  ^^ 
 +|  crc  |  0111'1001'0000'1110 
 +|  0x8000  |  1000'0000'0000'0000 
 +^  Résultat  |  1111'1001'0000'1110 
 + 
 +**=> crc = 0xF90E** 
 + 
 +<code c> b = b>>1; </code> 
 + 
 +^  b>> ^^ 
 +|  b  |  0000'0000'0000'0000 
 +^  b>> |  0000'0000'0000'0000 
 + 
 +**=> b = 0x0000** 
 + 
 +=== i= 1 === 
 +=== b = string [0] <=> '7' [0000'0000'0000'0111] === 
 + 
 +== bit_counter = 4 == 
 + 
 +<code c> feedback_bit = (crc ^ b) & 0x0001;</code> 
 +^  crc XOR b  ^^ 
 +|  crc  |  1111'1001'0000'1110 
 +|  b  |  0000'0000'0000'0111 
 +^ Résultat |  1111'1001'0000'1001 
 + 
 +^  (crc XOR b) & 0x0001  ^^ 
 +|crc XOR b  |  1111'1001'0000'1001 
 +|  0x0001  |  0000'0000'0000'0001 
 +^  Résultat  |  0000'0000'0000'0001 
 + 
 +**=> feedback_bit = 0x0001** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc ^ CRCPOLY16; </code> 
 + 
 +^  crc XOR CRCPOLY8  ^^ 
 +|  crc  |  1111'1001'0000'1110 
 +|  CRCPOLY16  |  0100'0000'0000'0010 
 +^  Résultat  |  1011'1001'0000'1100 
 + 
 +**=> crc = 0xB90C** 
 + 
 +<code c> crc = (crc >> 1) & 0x7FFF; </code> 
 + 
 +^  crc>> ^^ 
 +|  crc  |  1011'1001'0000'1100 
 +^  crc>> |  0101'1100'1000'0110 
 + 
 +^  (crc>>1) & 0x7FFF  ^^ 
 +|  crc>> |  0101'1100'1000'0110 
 +|  0x7FFF  |  0111'1111'1111'1111 
 +^ Résultat  |  0101'1100'1000'0110 
 + 
 +**=> crc = 0x5C86** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc | 0x80; </code> 
 + 
 +^  crc OR 0x8000  ^^ 
 +|  crc  |  0101'1100'1000'0110 
 +|  0x8000  |  1000'0000'0000'0000 
 +^  Résultat  |  1101'1100'1000'0110 
 + 
 +**=> crc = 0xDC86** 
 + 
 +<code c> b = b>>1; </code> 
 + 
 +^  b>> ^^ 
 +|  b  |  0000'0000'0000'0111 
 +^  b>> |  0000'0000'0000'0011 
 + 
 +**=> b = 0x0003** 
 + 
 + 
 +== bit_counter = 3 == 
 + 
 +<code c> feedback_bit = (crc ^ b) & 0x0001;</code> 
 +^  crc XOR b  ^^ 
 +|  crc  |  1101'1100'1000'0110 
 +|  b  |  0000'0000'0000'0011 
 +^ Résultat |  1101'1100'1000'0101 
 + 
 +^  (crc XOR b) & 0x0001  ^^ 
 +|crc XOR b  |  1101'1100'1000'0101 
 +|  0x0001  |  0000'0000'0000'0001 
 +^  Résultat  |  0000'0000'0000'0001 
 + 
 +**=> feedback_bit = 0x0001** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc ^ CRCPOLY16; </code> 
 + 
 +^  crc XOR CRCPOLY8  ^^ 
 +|  crc  |  1101'1100'1000'0110 
 +|  CRCPOLY16  |  0100'0000'0000'0010 
 +^  Résultat  |  1001'1100'1000'0100 
 + 
 +**=> crc = 0x9C84** 
 + 
 +<code c> crc = (crc >> 1) & 0x7FFF; </code> 
 + 
 +^  crc>> ^^ 
 +|  crc  |  1001'1100'1000'0100 
 +^  crc>> |  0100'1110'0100'0010 
 + 
 +^  (crc>>1) & 0x7FFF  ^^ 
 +|  crc>> |  0100'1110'0100'0010 
 +|  0x7FFF  |  0111'1111'1111'1111 
 +^ Résultat  |  0100'1110'0100'0010 
 + 
 +**=> crc = 0x4E42** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc | 0x80; </code> 
 + 
 +^  crc OR 0x8000  ^^ 
 +|  crc  |  0100'1110'0100'0010 
 +|  0x8000  |  1000'0000'0000'0000 
 +^  Résultat  |  1100'1110'0100'0010 
 + 
 +**=> crc = 0xCE42** 
 + 
 +<code c> b = b>>1; </code> 
 + 
 +^  b>> ^^ 
 +|  b  |  0000'0000'0000'0011 
 +^  b>> |  0000'0000'0000'0001 
 + 
 +**=> b = 0x0001** 
 + 
 +== bit_counter = 2 == 
 + 
 +<code c> feedback_bit = (crc ^ b) & 0x0001;</code> 
 +^  crc XOR b  ^^ 
 +|  crc  |  1100'1110'0100'0010 
 +|  b  |  0000'0000'0000'0001 
 +^ Résultat |  1100'1110'0100'0011 
 + 
 +^  (crc XOR b) & 0x0001  ^^ 
 +|crc XOR b  |  1100'1110'0100'0011 
 +|  0x0001  |  0000'0000'0000'0001 
 +^  Résultat  |  0000'0000'0000'0001 
 + 
 +**=> feedback_bit = 0x0001** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc ^ CRCPOLY16; </code> 
 + 
 +^  crc XOR CRCPOLY8  ^^ 
 +|  crc  |  1100'1110'0100'0010 
 +|  CRCPOLY16  |  0100'0000'0000'0010 
 +^  Résultat  |  1000'1110'0100'0000 
 + 
 +**=> crc = 0x8E40** 
 + 
 +<code c> crc = (crc >> 1) & 0x7FFF; </code> 
 + 
 +^  crc>> ^^ 
 +|  crc  |  1000'1110'0100'0000 
 +^  crc>> |  0100'0111'0010'0000 
 + 
 +^  (crc>>1) & 0x7FFF  ^^ 
 +|  crc>> |  0100'0111'0010'0000 
 +|  0x7FFF  |  0111'1111'1111'1111 
 +^ Résultat  |  0100'0111'0010'0000 
 + 
 +**=> crc = 0x4720** 
 + 
 +<code c> if (feedback_bit == 0x0001) crc = crc | 0x80; </code> 
 + 
 +^  crc OR 0x8000  ^^ 
 +|  crc  |  0100'0111'0010'0000 
 +|  0x8000  |  1000'0000'0000'0000 
 +^  Résultat  |  1100'0111'0010'0000 
 + 
 +**=> crc = 0xC720** 
 + 
 +<code c> b = b>>1; </code> 
 + 
 +^  b>> ^^ 
 +|  b  |  0000'0000'0000'0001 
 +^  b>> |  0000'0000'0000'0000 
 + 
 +**=> b = 0x0000** 
 + 
 +== bit_counter = 1 == 
 + 
 +<code c> feedback_bit = (crc ^ b) & 0x0001;</code> 
 +^  crc XOR b  ^^ 
 +|  crc  |  1100'0111'0010'0000 
 +|  b  |  0000'0000'0000'0000 
 +^ Résultat |  1100'0111'0010'0000 
 + 
 +^  (crc XOR b) & 0x0001  ^^ 
 +|crc XOR b  |  1100'0111'0010'0000 
 +|  0x0001  |  0000'0000'0000'0001 
 +^  Résultat  |  0000'0000'0000'0000 
 + 
 +**=> feedback_bit = 0x0000** 
 + 
 +<code c> crc = (crc >> 1) & 0x7FFF; </code> 
 + 
 +^  crc>> ^^ 
 +|  crc  |  1100'0111'0010'0000 
 +^  crc>> |  0110'0011'1001'0000 
 + 
 +^  (crc>>1) & 0x7FFF  ^^ 
 +|  crc>> |  0110'0011'1001'0000 
 +|  0x7FFF  |  0111'1111'1111'1111 
 +^ Résultat  |  0110'0011'1001'0000 
 + 
 +**=> crc = 0x6390**
onewire/crc.1337087229.txt.gz · Last modified: 2012/05/15 13:07 by fdc