diff --git a/core/esp_spi.c b/core/esp_spi.c
index ab33ea4..720da18 100644
--- a/core/esp_spi.c
+++ b/core/esp_spi.c
@@ -27,6 +27,7 @@
 #define _SPI1_FUNC IOMUX_FUNC(2)
 
 #define _SPI_BUF_SIZE 64
+#define __min(a,b) ((a > b) ? (b):(a))
 
 static bool _minimal_pins[2] = {false, false};
 
@@ -244,3 +245,36 @@ size_t spi_transfer(uint8_t bus, const void *out_data, void *in_data, size_t len
 
     return len;
 }
+
+static void _repeat_send(uint8_t bus, uint32_t* dword,int32_t* repeats,spi_word_size_t size)
+{
+    uint8_t i = 0 ;
+    while(*repeats > 0)
+    {
+        uint16_t bytes_to_transfer = __min(*repeats * size , _SPI_BUF_SIZE);
+        _wait(bus);
+        _set_size(bus,bytes_to_transfer);
+        for(i = 0; i < (bytes_to_transfer + 3) / 4;i++)
+            SPI(bus).W[i] = *dword; //need test with memcpy !
+        _start(bus);
+        *repeats -= (bytes_to_transfer / size ) ;
+    }
+    _wait(bus);
+}
+
+void spi_repeat_send_8(uint8_t bus, uint8_t data,int32_t repeats)
+{
+    uint32_t dword = data << 24 | data << 16 | data << 8 | data;
+    _repeat_send(bus,&dword,&repeats, SPI_8BIT);
+}
+
+void spi_repeat_send_16(uint8_t bus, uint16_t data,int32_t repeats)
+{
+    uint32_t dword = data << 16 | data;
+    _repeat_send(bus,&dword,&repeats, SPI_16BIT);
+}
+
+void spi_repeat_send_32(uint8_t bus, uint32_t data,int32_t repeats)
+{
+    _repeat_send(bus,&data,&repeats, SPI_32BIT);
+}
diff --git a/core/include/esp/spi.h b/core/include/esp/spi.h
index b3bc629..4b31144 100644
--- a/core/include/esp/spi.h
+++ b/core/include/esp/spi.h
@@ -36,6 +36,15 @@
 #define SPI_FREQ_DIV_40M  SPI_GET_FREQ_DIV(1,  2)  ///< 40MHz
 #define SPI_FREQ_DIV_80M  SPI_GET_FREQ_DIV(1,  1)  ///< 80MHz
 
+/*
+ * Possible Data Structure of SPI Transaction
+ *
+ * [COMMAND]+[ADDRESS]+[DataOUT]+[DUMMYBITS]+[DataIN]
+ *
+ * [COMMAND]+[ADDRESS]+[DUMMYBITS]+[DataOUT]
+ *
+ */
+
 #ifdef __cplusplus
 extern "C"
 {
@@ -177,7 +186,7 @@ void spi_set_frequency_div(uint8_t bus, uint32_t divider);
 inline uint32_t spi_get_frequency_div(uint8_t bus)
 {
     return (FIELD2VAL(SPI_CLOCK_DIV_PRE, SPI(bus).CLOCK) + 1) |
-           (FIELD2VAL(SPI_CLOCK_COUNT_NUM, SPI(bus).CLOCK) + 1);
+            (FIELD2VAL(SPI_CLOCK_COUNT_NUM, SPI(bus).CLOCK) + 1);
 }
 /**
  * \brief Get SPI bus frequency in Hz
@@ -187,8 +196,8 @@ inline uint32_t spi_get_frequency_div(uint8_t bus)
 inline uint32_t spi_get_frequency_hz(uint8_t bus)
 {
     return APB_CLK_FREQ /
-        (FIELD2VAL(SPI_CLOCK_DIV_PRE, SPI(bus).CLOCK) + 1) /
-        (FIELD2VAL(SPI_CLOCK_COUNT_NUM, SPI(bus).CLOCK) + 1);
+            (FIELD2VAL(SPI_CLOCK_DIV_PRE, SPI(bus).CLOCK) + 1) /
+            (FIELD2VAL(SPI_CLOCK_COUNT_NUM, SPI(bus).CLOCK) + 1);
 }
 
 /**
@@ -221,8 +230,8 @@ void spi_set_endianness(uint8_t bus, spi_endianness_t endianness);
 inline spi_endianness_t spi_get_endianness(uint8_t bus)
 {
     return SPI(bus).USER0 & (SPI_USER0_WR_BYTE_ORDER | SPI_USER0_RD_BYTE_ORDER)
-        ? SPI_BIG_ENDIAN
-        : SPI_LITTLE_ENDIAN;
+            ? SPI_BIG_ENDIAN
+                    : SPI_LITTLE_ENDIAN;
 }
 
 /**
@@ -265,6 +274,129 @@ uint32_t spi_transfer_32(uint8_t bus, uint32_t data);
  */
 size_t spi_transfer(uint8_t bus, const void *out_data, void *in_data, size_t len, spi_word_size_t word_size);
 
+/**
+ * \brief Add permanent command bits when transfert data over SPI
+ * Example:
+ *
+ *    spi_set_command(1,1,0x01); // Set one command bit to 1
+ *    for (uint8_t i = 0 ; i < x ; i++ ) {
+ *    	spi_transfer_8(1,0x55);  // Send 1 bit command + 8 bits data x times
+ *    }
+ *    spi_clear_command(1); // Clear command
+ *    spi_transfer_8(1,0x55);  // Send 8 bits data
+ *
+ * \param bus Bus ID: 0 - system, 1 - user
+ * \param bits Number of bits (max: 16).
+ * \param data Command to send for each transfert.
+ */
+static inline void spi_set_command(uint8_t bus,uint8_t bits, uint16_t data)
+{
+    if(!bits) return ;
+    SPI(bus).USER0 |= SPI_USER0_COMMAND ; //enable COMMAND function in SPI module
+    uint16_t command = data << (16-bits); //align command data to high bits
+    command = ((command>>8)&0xff) | ((command<<8)&0xff00); //swap byte order
+    SPI(bus).USER2 =  SET_FIELD(SPI(bus).USER2, SPI_USER2_COMMAND_BITLEN, --bits);
+    SPI(bus).USER2 =  SET_FIELD(SPI(bus).USER2, SPI_USER2_COMMAND_VALUE, command);
+}
+
+/**
+ * \brief Add permanent address bits when transfert data over SPI
+ * Example:
+ *
+ *    spi_set_address(1,8,0x45); // Set one address byte to 0x45
+ *    for (uint8_t i = 0 ; i < x ; i++ ) {
+ *    	spi_transfer_16(1,0xC584);  // Send 16 bits address + 16 bits data x times
+ *    }
+ *    spi_clear_address(1); // Clear command
+ *    spi_transfer_16(1,0x55);  // Send 16 bits data
+ *
+ * \param bus Bus ID: 0 - system, 1 - user
+ * \param bits Number of bits (max: 32).
+ * \param data Address to send for each transfert.
+ */
+static inline void spi_set_address(uint8_t bus,uint8_t bits, uint32_t data)
+{
+    if(!bits) return ;
+    SPI(bus).USER1 = SET_FIELD(SPI(bus).USER1, SPI_USER1_ADDR_BITLEN, --bits);
+    SPI(bus).USER0 |= SPI_USER0_ADDR ; //enable ADDRess function in SPI module
+    SPI(bus).ADDR = data<<(32-bits) ; //align address data to high bits
+}
+
+/**
+ * \brief Add permanent dummy bits when transfert data over SPI
+ * Example:
+ *
+ *    spi_set_dummy_bits(1,4,false); // Set 4 dummy bit before Dout
+ *    for (uint8_t i = 0 ; i < x ; i++ ) {
+ *    	spi_transfer_16(1,0xC584);  // Send 4 bits dummy + 16 bits Dout x times
+ *    }
+ *    spi_set_dummy_bits(1,4,true); // Set 4 dummy bit between Dout and Din
+ *    spi_transfer_8(1,0x55);  // Send 8 bits Dout + 4 bits dummy + 8 bits Din
+ *
+ * \param bus Bus ID: 0 - system, 1 - user
+ * \param bits Number of bits
+ * \param pos Position of dummy bit, between Dout and Din if true.
+ */
+static inline void spi_set_dummy_bits(uint8_t bus, uint8_t bits, bool pos)
+{
+    if(!bits) return ;
+    if(pos) { SPI(bus).USER0 |= SPI_USER0_MISO; } // Dummy bit will be between Dout and Din data if set
+    SPI(bus).USER0 |= SPI_USER0_DUMMY; //enable dummy bits
+    SPI(bus).USER1 = SET_FIELD(SPI(bus).USER1, SPI_USER1_DUMMY_CYCLELEN, --bits);
+}
+
+/**
+ * \brief Clear adress Bits
+ * \param bus Bus ID: 0 - system, 1 - user
+ */
+static inline void spi_clear_address(uint8_t bus)
+{
+    SPI(bus).USER0 &= ~(SPI_USER0_ADDR) ;
+}
+
+/**
+ * \brief Clear command Bits
+ * \param bus Bus ID: 0 - system, 1 - user
+ */
+
+static inline void spi_clear_command(uint8_t bus)
+{
+    SPI(bus).USER0 &= ~(SPI_USER0_COMMAND) ;
+}
+
+/**
+ * \brief Clear dummy Bits
+ * \param bus Bus ID: 0 - system, 1 - user
+ */
+static inline void spi_clear_dummy(uint8_t bus)
+{
+    SPI(bus).USER0 &= ~(SPI_USER0_DUMMY | SPI_USER0_MISO);
+}
+
+/**
+ * \brief Send many 8 bits template over SPI
+ * \param bus Bus ID: 0 - system, 1 - user
+ * \param data Byte template (8 bits)
+ * \param repeats Copy byte number
+ */
+void spi_repeat_send_8(uint8_t bus, uint8_t data, int32_t repeats);
+
+/**
+ * \brief Send many 16 bits template over SPI
+ * \param bus Bus ID: 0 - system, 1 - user
+ * \param data Word template (16 bits)
+ * \param repeats Copy word number
+ */
+void spi_repeat_send_16(uint8_t bus, uint16_t data, int32_t repeats);
+
+/**
+ * \brief Send many 32 bits template over SPI
+ * \param bus Bus ID: 0 - system, 1 - user
+ * \param data Dualword template (32 bits)
+ * \param repeats Copy dword number
+ */
+void spi_repeat_send_32(uint8_t bus, uint32_t data, int32_t repeats);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/examples/spi_test/Makefile b/examples/spi_test/Makefile
new file mode 100644
index 0000000..f28ce0c
--- /dev/null
+++ b/examples/spi_test/Makefile
@@ -0,0 +1,3 @@
+# Simple makefile for simple example
+PROGRAM=spi_test
+include ../../common.mk
diff --git a/examples/spi_test/spi_test.c b/examples/spi_test/spi_test.c
new file mode 100644
index 0000000..0baccc3
--- /dev/null
+++ b/examples/spi_test/spi_test.c
@@ -0,0 +1,64 @@
+/* Example SPI transfert
+ *
+ * This sample code is in the public domain.
+ */
+#include "espressif/esp_common.h"
+#include "esp/uart.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "esp8266.h"
+#include <stdio.h>
+#include "esp/spi.h"
+
+/*
+ * Possible Data Structure of SPI Transaction
+ *
+ * [COMMAND]+[ADDRESS]+[DataOUT]+[DUMMYBITS]+[DataIN]
+ *
+ * [COMMAND]+[ADDRESS]+[DUMMYBITS]+[DataOUT]
+ *
+ */
+
+
+void loop(void *pvParameters)
+{
+    uint32_t time = 0 ; // SPI transmission time
+    float avr_time = 0 ; // Average of SPI transmission
+    float u = 0 ;
+
+    spi_init(1, SPI_MODE0, SPI_FREQ_DIV_1M, 1, SPI_LITTLE_ENDIAN, false); // init SPI module
+
+
+    while(1) {
+
+        time = sdk_system_get_time();
+
+        spi_set_command(1,1,1) ; // Set one command bit to 1
+        spi_set_address(1,4,8) ; // Set 4 address bits to 8
+        spi_set_dummy_bits(1,4,false); // Set 4 dummy bit before Dout
+
+        spi_repeat_send_16(1,0xC584,10);  // Send 1 bit command + 4 bits address + 4 bits dummy + 160 bits data
+
+        spi_clear_address(1); // remove address
+        spi_clear_command(1); // remove command
+        spi_clear_dummy(1); // remove dummy
+
+
+        time = sdk_system_get_time() -time ;
+        avr_time = ((avr_time * (float)u ) + (float)time)/((float)u+1.0)  ; // compute average
+        u++;
+        if (u==100) {
+            u=0 ;
+            printf("Time: %f\n",avr_time);
+        }
+        vTaskDelay(100/portTICK_PERIOD_MS);
+    }
+}
+
+
+void user_init(void)
+{
+    uart_set_baud(0, 115200);
+    printf("SDK version:%s\n", sdk_system_get_sdk_version());
+    xTaskCreate(loop, "loop", 1024, NULL, 2, NULL);
+}