Просмотр исходного кода

lcd: spi-lcd send command and parameter with big-endian

morris 4 лет назад
Родитель
Сommit
a6661bdf90

+ 32 - 0
components/esp_lcd/src/esp_lcd_panel_io_spi.c

@@ -15,6 +15,7 @@
 #include "driver/gpio.h"
 #include "esp_log.h"
 #include "esp_check.h"
+#include "esp_lcd_common.h"
 
 static const char *TAG = "lcd_panel.io.spi";
 
@@ -131,6 +132,34 @@ err:
     return ret;
 }
 
+static void spi_lcd_prepare_cmd_buffer(esp_lcd_panel_io_spi_t *panel_io, const void *cmd)
+{
+    uint8_t *from = (uint8_t *)cmd;
+    // LCD is big-endian, e.g. to send command 0x1234, byte 0x12 should appear on the bus first
+    // However, the SPI peripheral will send 0x34 first, so we reversed the order below
+    if (panel_io->lcd_cmd_bits > 8) {
+        int start = 0;
+        int end = panel_io->lcd_cmd_bits / 8 - 1;
+        lcd_com_reverse_buffer_bytes(from, start, end);
+    }
+}
+
+static void spi_lcd_prepare_param_buffer(esp_lcd_panel_io_spi_t *panel_io, const void *param, size_t param_size)
+{
+    uint8_t *from = (uint8_t *)param;
+    int param_width = panel_io->lcd_param_bits / 8;
+    size_t param_num = param_size / param_width;
+    // LCD is big-endian, e.g. to send command 0x1234, byte 0x12 should appear on the bus first
+    // However, the SPI peripheral will send 0x34 first, so we reversed the order below
+    if (panel_io->lcd_param_bits > 8) {
+        for (size_t i = 0; i < param_num; i++) {
+            int start = i * param_width;
+            int end = start + param_width - 1;
+            lcd_com_reverse_buffer_bytes(from, start, end);
+        }
+    }
+}
+
 static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size)
 {
     esp_err_t ret = ESP_OK;
@@ -146,6 +175,7 @@ static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons
     spi_panel_io->num_trans_inflight = 0;
     lcd_trans = &spi_panel_io->trans_pool[0];
     memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t));
+    spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd);
     lcd_trans->base.user = spi_panel_io;
     lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode
     lcd_trans->base.length = spi_panel_io->lcd_cmd_bits;
@@ -162,6 +192,7 @@ static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons
     ESP_GOTO_ON_ERROR(ret, err, TAG, "spi transmit (polling) command failed");
 
     if (param && param_size) {
+        spi_lcd_prepare_param_buffer(spi_panel_io, param, param_size);
         lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_data_level; // set D/C line to data mode
         lcd_trans->base.length = param_size * 8; // transaction length is in bits
         lcd_trans->base.tx_buffer = param;
@@ -192,6 +223,7 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
     spi_panel_io->num_trans_inflight = 0;
     lcd_trans = &spi_panel_io->trans_pool[0];
     memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t));
+    spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd);
     lcd_trans->base.user = spi_panel_io;
     lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode
     lcd_trans->base.length = spi_panel_io->lcd_cmd_bits;

+ 23 - 22
components/esp_lcd/test/test_rgb_panel.c

@@ -8,27 +8,28 @@
 
 #define TEST_LCD_H_RES         (480)
 #define TEST_LCD_V_RES         (272)
-#define TEST_LCD_VSYNC_GPIO    (1)
-#define TEST_LCD_HSYNC_GPIO    (2)
-#define TEST_LCD_DE_GPIO       (-1)
-#define TEST_LCD_PCLK_GPIO     (3)
-#define TEST_LCD_DATA0_GPIO    (4)  // B0
-#define TEST_LCD_DATA1_GPIO    (5)  // B1
-#define TEST_LCD_DATA2_GPIO    (6)  // B2
-#define TEST_LCD_DATA3_GPIO    (7)  // B3
-#define TEST_LCD_DATA4_GPIO    (8)  // B4
-#define TEST_LCD_DATA5_GPIO    (9)  // G0
-#define TEST_LCD_DATA6_GPIO    (10) // G1
-#define TEST_LCD_DATA7_GPIO    (11) // G2
-#define TEST_LCD_DATA8_GPIO    (12) // G3
-#define TEST_LCD_DATA9_GPIO    (13) // G4
-#define TEST_LCD_DATA10_GPIO   (14) // G5
-#define TEST_LCD_DATA11_GPIO   (15) // R0
-#define TEST_LCD_DATA12_GPIO   (16) // R1
-#define TEST_LCD_DATA13_GPIO   (17) // R2
-#define TEST_LCD_DATA14_GPIO   (18) // R3
-#define TEST_LCD_DATA15_GPIO   (19) // R4
-#define TEST_LCD_DISP_EN_GPIO  (-1)
+
+#define TEST_LCD_VSYNC_GPIO    (48)
+#define TEST_LCD_HSYNC_GPIO    (47)
+#define TEST_LCD_DE_GPIO       (45)
+#define TEST_LCD_PCLK_GPIO     (21)
+#define TEST_LCD_DATA0_GPIO    (3)  // B0
+#define TEST_LCD_DATA1_GPIO    (4)  // B1
+#define TEST_LCD_DATA2_GPIO    (5)  // B2
+#define TEST_LCD_DATA3_GPIO    (6)  // B3
+#define TEST_LCD_DATA4_GPIO    (7)  // B4
+#define TEST_LCD_DATA5_GPIO    (8)  // G0
+#define TEST_LCD_DATA6_GPIO    (9)  // G1
+#define TEST_LCD_DATA7_GPIO    (10) // G2
+#define TEST_LCD_DATA8_GPIO    (11) // G3
+#define TEST_LCD_DATA9_GPIO    (12) // G4
+#define TEST_LCD_DATA10_GPIO   (13) // G5
+#define TEST_LCD_DATA11_GPIO   (14) // R0
+#define TEST_LCD_DATA12_GPIO   (15) // R1
+#define TEST_LCD_DATA13_GPIO   (16) // R2
+#define TEST_LCD_DATA14_GPIO   (17) // R3
+#define TEST_LCD_DATA15_GPIO   (18) // R4
+#define TEST_LCD_DISP_EN_GPIO  (39)
 
 #if SOC_LCD_RGB_SUPPORTED
 // RGB driver consumes a huge memory to save frame buffer, only test it with PSRAM enabled
@@ -66,7 +67,7 @@ TEST_CASE("lcd rgb lcd panel", "[lcd]")
             TEST_LCD_DATA15_GPIO,
         },
         .timings = {
-            .pclk_hz = 6000000,
+            .pclk_hz = 12000000,
             .h_res = TEST_LCD_H_RES,
             .v_res = TEST_LCD_V_RES,
             .hsync_back_porch = 43,

+ 101 - 15
components/esp_lcd/test/test_spi_lcd_panel.c

@@ -17,7 +17,7 @@
 
 typedef bool (*trans_done_callback_t)(esp_lcd_panel_io_handle_t, void *, void *);
 
-static void lcd_initialize_spi(esp_lcd_panel_io_handle_t *io_handle, esp_lcd_panel_handle_t *panel_handle, trans_done_callback_t on_color_trans_done, void *user_data, bool oct_mode)
+static void lcd_initialize_spi(esp_lcd_panel_io_handle_t *io_handle, trans_done_callback_t on_color_trans_done, void *user_data, int cmd_bits, int param_bits, bool oct_mode)
 {
     gpio_config_t bk_gpio_config = {
         .mode = GPIO_MODE_OUTPUT,
@@ -51,8 +51,8 @@ static void lcd_initialize_spi(esp_lcd_panel_io_handle_t *io_handle, esp_lcd_pan
         .pclk_hz = TEST_LCD_PIXEL_CLOCK_HZ,
         .spi_mode = 0,
         .trans_queue_depth = 10,
-        .lcd_cmd_bits = 8,
-        .lcd_param_bits = 8,
+        .lcd_cmd_bits = cmd_bits,
+        .lcd_param_bits = param_bits,
         .on_color_trans_done = on_color_trans_done,
         .user_data = user_data
     };
@@ -61,13 +61,6 @@ static void lcd_initialize_spi(esp_lcd_panel_io_handle_t *io_handle, esp_lcd_pan
         io_config.spi_mode = 3;
     }
     TEST_ESP_OK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)TEST_SPI_HOST_ID, &io_config, io_handle));
-
-    esp_lcd_panel_dev_config_t panel_config = {
-        .reset_gpio_num = TEST_LCD_RST_GPIO,
-        .color_space = ESP_LCD_COLOR_SPACE_RGB,
-        .bits_per_pixel = 16,
-    };
-    TEST_ESP_OK(esp_lcd_new_panel_st7789(*io_handle, &panel_config, panel_handle));
 }
 
 static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle)
@@ -103,12 +96,74 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha
 #undef TEST_IMG_SIZE
 }
 
+TEST_CASE("lcd panel spi io test", "[lcd]")
+{
+    esp_lcd_panel_io_handle_t io_handle = NULL;
+    lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, false);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) {
+        0x11, 0x22, 0x33
+    }, 3);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0);
+    TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
+    TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
+
+    lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, false);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) {
+        0x11, 0x22, 0x33
+    }, 6);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0);
+    TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
+    TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
+
+#if SOC_SPI_SUPPORT_OCT
+    lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, true);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) {
+        0x11, 0x22, 0x33
+    }, 3);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0);
+    TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
+    TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
+
+    lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, true);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) {
+        0x11, 0x22, 0x33
+    }, 6);
+    esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0);
+    TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
+    TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
+#endif // SOC_SPI_SUPPORT_OCT
+}
+
 #if SOC_SPI_SUPPORT_OCT
 TEST_CASE("lcd panel with 8-line spi interface (st7789)", "[lcd]")
 {
     esp_lcd_panel_io_handle_t io_handle = NULL;
     esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, &panel_handle, NULL, NULL, true);
+    lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, true);
+    esp_lcd_panel_dev_config_t panel_config = {
+        .reset_gpio_num = TEST_LCD_RST_GPIO,
+        .color_space = ESP_LCD_COLOR_SPACE_RGB,
+        .bits_per_pixel = 16,
+    };
+    TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
+    lcd_panel_test(io_handle, panel_handle);
+}
+
+TEST_CASE("lcd panel with 8-line spi interface (nt35510)", "[lcd]")
+{
+    esp_lcd_panel_io_handle_t io_handle = NULL;
+    esp_lcd_panel_handle_t panel_handle = NULL;
+    lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, true);
+    esp_lcd_panel_dev_config_t panel_config = {
+        .reset_gpio_num = TEST_LCD_RST_GPIO,
+        .color_space = ESP_LCD_COLOR_SPACE_RGB,
+        .bits_per_pixel = 16,
+    };
+    TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
     lcd_panel_test(io_handle, panel_handle);
 }
 #endif // SOC_SPI_SUPPORT_OCT
@@ -117,7 +172,13 @@ TEST_CASE("lcd panel with 1-line spi interface (st7789)", "[lcd]")
 {
     esp_lcd_panel_io_handle_t io_handle = NULL;
     esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, &panel_handle, NULL, NULL, false);
+    lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, false);
+    esp_lcd_panel_dev_config_t panel_config = {
+        .reset_gpio_num = TEST_LCD_RST_GPIO,
+        .color_space = ESP_LCD_COLOR_SPACE_RGB,
+        .bits_per_pixel = 16,
+    };
+    TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
     lcd_panel_test(io_handle, panel_handle);
 }
 
@@ -156,8 +217,28 @@ TEST_CASE("lvgl gui with 8-line spi interface (st7789)", "[lcd][lvgl][ignore]")
     lv_disp_t *disp = NULL;
     esp_lcd_panel_io_handle_t io_handle = NULL;
     esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, &panel_handle, notify_lvgl_ready_to_flush, &disp, true);
+    lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 8, 8, true);
+    esp_lcd_panel_dev_config_t panel_config = {
+        .reset_gpio_num = TEST_LCD_RST_GPIO,
+        .color_space = ESP_LCD_COLOR_SPACE_RGB,
+        .bits_per_pixel = 16,
+    };
+    TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
+    lvgl_gui_test(io_handle, panel_handle, &disp);
+}
 
+TEST_CASE("lvgl gui with 8-line spi interface (nt35510)", "[lcd][lvgl][ignore]")
+{
+    lv_disp_t *disp = NULL;
+    esp_lcd_panel_io_handle_t io_handle = NULL;
+    esp_lcd_panel_handle_t panel_handle = NULL;
+    lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 16, 16, true);
+    esp_lcd_panel_dev_config_t panel_config = {
+        .reset_gpio_num = TEST_LCD_RST_GPIO,
+        .color_space = ESP_LCD_COLOR_SPACE_RGB,
+        .bits_per_pixel = 16,
+    };
+    TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
     lvgl_gui_test(io_handle, panel_handle, &disp);
 }
 #endif // SOC_SPI_SUPPORT_OCT
@@ -167,8 +248,13 @@ TEST_CASE("lvgl gui with 1-line spi interface (st7789)", "[lcd][lvgl][ignore]")
     lv_disp_t *disp = NULL;
     esp_lcd_panel_io_handle_t io_handle = NULL;
     esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, &panel_handle, notify_lvgl_ready_to_flush, &disp, false);
-
+    lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 8, 8, false);
+    esp_lcd_panel_dev_config_t panel_config = {
+        .reset_gpio_num = TEST_LCD_RST_GPIO,
+        .color_space = ESP_LCD_COLOR_SPACE_RGB,
+        .bits_per_pixel = 16,
+    };
+    TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
     lvgl_gui_test(io_handle, panel_handle, &disp);
 }
 

+ 40 - 40
docs/en/api-reference/peripherals/spi_master.rst

@@ -158,49 +158,49 @@ Supported line modes for {IDF_TARGET_NAME} are listed as follows, to make use of
 
 .. only:: not SOC_SPI_SUPPORT_OCT
 
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Mode name    | Command Line Width | Address Line Width | Data Line Width | Transaction Flag           | Bus IO setting Flag     |
-+==============+====================+====================+=================+============================+=========================+
-| Normal SPI   | 1                  | 1                  | 1               | 0                          | 0                       |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Dual Output  | 1                  | 1                  | 2               | SPI_TRANS_MODE_DIO         |                         |
-|              |                    |                    |                 |                            |                         |
-|              |                    |                    |                 |                            | SPICOMMON_BUSFLAG_DUAL  |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Dual I/O     | 1                  | 2                  | 2               | SPI_TRANS_MODE_DIO |       |                         |
-|              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR   |                         |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Quad Output  | 1                  | 1                  | 4               | SPI_TRANS_MODE_QIO         |                         |
-+--------------+--------------------+--------------------+-----------------+----------------------------+                         |
-| Quad I/O     | 1                  | 4                  | 4               | SPI_TRANS_MODE_QIO |       | SPICOMMON_BUSFLAG_QUAD  |
-|              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR   |                         |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Mode name    | Command Line Width | Address Line Width | Data Line Width | Transaction Flag           | Bus IO setting Flag     |
+    +==============+====================+====================+=================+============================+=========================+
+    | Normal SPI   | 1                  | 1                  | 1               | 0                          | 0                       |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Dual Output  | 1                  | 1                  | 2               | SPI_TRANS_MODE_DIO         |                         |
+    |              |                    |                    |                 |                            |                         |
+    |              |                    |                    |                 |                            | SPICOMMON_BUSFLAG_DUAL  |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Dual I/O     | 1                  | 2                  | 2               | SPI_TRANS_MODE_DIO |       |                         |
+    |              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR   |                         |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Quad Output  | 1                  | 1                  | 4               | SPI_TRANS_MODE_QIO         |                         |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+                         |
+    | Quad I/O     | 1                  | 4                  | 4               | SPI_TRANS_MODE_QIO |       | SPICOMMON_BUSFLAG_QUAD  |
+    |              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR   |                         |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
 
 .. only:: SOC_SPI_SUPPORT_OCT
 
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Mode name    | Command Line Width | Address Line Width | Data Line Width | Transaction Flag           | Bus IO setting Flag     |
-+==============+====================+====================+=================+============================+=========================+
-| Normal SPI   | 1                  | 1                  | 1               | 0                          | 0                       |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Dual Output  | 1                  | 1                  | 2               | SPI_TRANS_MODE_DIO         |                         |
-|              |                    |                    |                 |                            |                         |
-|              |                    |                    |                 |                            | SPICOMMON_BUSFLAG_DUAL  |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Dual I/O     | 1                  | 2                  | 2               | SPI_TRANS_MODE_DIO |       |                         |
-|              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR   |                         |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Quad Output  | 1                  | 1                  | 4               | SPI_TRANS_MODE_QIO         |                         |
-+--------------+--------------------+--------------------+-----------------+----------------------------+                         |
-| Quad I/O     | 1                  | 4                  | 4               | SPI_TRANS_MODE_QIO |       | SPICOMMON_BUSFLAG_QUAD  |
-|              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR   |                         |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
-| Octal Output | 1                  | 1                  | 8               | SPI_TRANS_MODE_OCT         |                         |
-+--------------+--------------------+--------------------+-----------------+----------------------------+                         |
-| OPI          | 8                  | 8                  | 8               | SPI_TRANS_MODE_OCT |       | SPICOMMON_BUSFLAG_OCTAL |
-|              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR | |                         |
-|              |                    |                    |                 | SPI_TRANS_MULTILINE_CMD    |                         |
-+--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Mode name    | Command Line Width | Address Line Width | Data Line Width | Transaction Flag           | Bus IO setting Flag     |
+    +==============+====================+====================+=================+============================+=========================+
+    | Normal SPI   | 1                  | 1                  | 1               | 0                          | 0                       |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Dual Output  | 1                  | 1                  | 2               | SPI_TRANS_MODE_DIO         |                         |
+    |              |                    |                    |                 |                            |                         |
+    |              |                    |                    |                 |                            | SPICOMMON_BUSFLAG_DUAL  |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Dual I/O     | 1                  | 2                  | 2               | SPI_TRANS_MODE_DIO |       |                         |
+    |              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR   |                         |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Quad Output  | 1                  | 1                  | 4               | SPI_TRANS_MODE_QIO         |                         |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+                         |
+    | Quad I/O     | 1                  | 4                  | 4               | SPI_TRANS_MODE_QIO |       | SPICOMMON_BUSFLAG_QUAD  |
+    |              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR   |                         |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
+    | Octal Output | 1                  | 1                  | 8               | SPI_TRANS_MODE_OCT         |                         |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+                         |
+    | OPI          | 8                  | 8                  | 8               | SPI_TRANS_MODE_OCT |       | SPICOMMON_BUSFLAG_OCTAL |
+    |              |                    |                    |                 | SPI_TRANS_MULTILINE_ADDR | |                         |
+    |              |                    |                    |                 | SPI_TRANS_MULTILINE_CMD    |                         |
+    +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
 
 Command and Address Phases
 ^^^^^^^^^^^^^^^^^^^^^^^^^^