AMB82-MINI無法驅動I2C OLED屏,無法打開promiscuous mode

大家好!之前在臉書發過這個提問,沒人理我,也可能這倆問題非常困難,
我想把之前RTL8722DM的項目移植到AMB82-MINI上,遇到兩個問題,一個問題是使用Adafruit_SSD1306庫來驅動一塊128x64的4引脚OLED屏,在AMB82-MINI無顯示,但是同樣代碼在之前的RTL8722DM可以正常顯示,後來發現修改在調用Wire發送指令之後,稍微延遲一段時間,就可以花屏顯示、然後調節延時增多,就可以正常顯示,但問題是這樣做刷屏效率很低。另外一個問題,之前的代碼在RTL8722DM上可以開啓混雜模式,可以監聽到所有類型數據包,但是相同的代碼在AMB82-MINI上,雖然顯示成功開啓混雜模式,但是只能監聽到信標幀和探測請求幀,無法監聽到其它類型,請問該如何解決?謝謝!

Hi @OLCo,
您好,歡迎來到AmebaIoT官方論壇。非常抱歉之前沒有答復您的貼文在FB上,這兩周我們在做一些AmebaPro2 Arduino 使用上的優化,所以fb的問題會延遲回答。
目前我們手上只有ST7735S driver 的 I2C 屏幕,您提到的SSD1306 庫中遇到的問題我們暫時無法復現。我們會儘快安排元件購買并幫助您debug。
謝謝

非常感謝你的答復,下面是我精簡優化顯示庫之後,用來測試的Arduino項目代碼,請看下有沒有參考價值,其中254、263、286、297行的延時代碼,如果在RTL8722DM、RTL8720DN不需要延時,而在AMB82-MINI則需要加入延時,雖然這樣OLED屏幕顯示了,但是感覺不完美、不極緻

/** This is used for testing the I2C OLED screen with the AMB82-MINI development board.
** The OLED screen has 4 pins and is driven by the I2C SSD1306 driver.
** Ruyi OS 2023-05-29
** Email:ruyiboy2021@gmail.com
**/

/** No other library files are required, only Wire.h needs to be included. **/
#include <Wire.h>

#define RUYI_COLOR_BLACK 0
#define RUYI_COLOR_WHITE 1
#define RUYI_IIC_DATA_LENGTH 128
#define RUYI_IIC_CLOCK 400000
#define RUYI_IIC_ADDRESS 0x3C
#define RUYI_IIC_CO_DC 0x00
#define RUYI_GRAPHICS_MEMORY 1024
#define RUYI_DIV_OPTIMIZATION 0x1999999A

static uint8_t main_graphics_memory[RUYI_GRAPHICS_MEMORY];
static uint8_t command_list_1[5] PROGMEM =
{ 0x22, 0x00, 0xFF, 0x21, 0x00};
static uint8_t command_list_2[4] PROGMEM =
{ 0xAE, 0xD5, 0x80, 0xA8};
static uint8_t command_list_3[4] PROGMEM =
{ 0xD3, 0x00, 0x40, 0x8D};
static uint8_t command_list_4[4] PROGMEM =
{ 0x20, 0x00, 0xA1, 0xC8};
static uint8_t command_list_5[6] PROGMEM =
{ 0xDB, 0x40, 0xA4, 0xA6, 0x2E, 0xAF};

//29X29
static const uint8_t BUDDHA_BITMAP[116] PROGMEM =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00,
0x7F, 0xF0, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x07,
0xFF, 0xFF, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x03, 0x00, 0x04,
0xF9, 0xF1, 0x00, 0x04, 0x09, 0x01, 0x00, 0x06, 0x00, 0x03, 0x00, 0x01,
0x0F, 0x04, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x03,
0x88, 0x8E, 0x00, 0x04, 0x08, 0x81, 0x00, 0x08, 0x87, 0x08, 0x80, 0x08,
0x40, 0x10, 0x80, 0x0C, 0x38, 0xE0, 0x80, 0x03, 0x48, 0x93, 0x00, 0x0C,
0xF4, 0x7C, 0x80, 0x08, 0x06, 0x80, 0x80, 0x08, 0x09, 0x80, 0x80, 0x04,
0x08, 0x41, 0x00, 0x03, 0x08, 0x42, 0x00, 0x00, 0xF7, 0xFC, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

//5X7
static const uint8_t NUMBER_FONTS[10][5] PROGMEM =
{
{ 0x3E, 0x51, 0x49, 0x45, 0x3E}, /** 0 /
{ 0x00, 0x42, 0x7F, 0x40, 0x00}, /
1 /
{ 0x72, 0x49, 0x49, 0x49, 0x46}, /
2 /
{ 0x21, 0x41, 0x49, 0x4D, 0x33}, /
3 /
{ 0x18, 0x14, 0x12, 0x7F, 0x10}, /
4 /
{ 0x27, 0x45, 0x45, 0x45, 0x39}, /
5 /
{ 0x3C, 0x4A, 0x49, 0x49, 0x31}, /
6 /
{ 0x41, 0x21, 0x11, 0x09, 0x07}, /
7 /
{ 0x36, 0x49, 0x49, 0x49, 0x36}, /
8 /
{ 0x46, 0x49, 0x49, 0x29, 0x1E} /
9 **/
};

static void ruyi_draw_white_number(uint32_t x, uint32_t y, const uint8_t *bitmap)
{
uint32_t w = 0;
uint32_t h = 0;
uint32_t ny = 0;
uint8_t nc = 0;
do
{
nc = *(bitmap + w);
h = 0;
do
{
if (nc & 0x01)
{
ny = y + h;
*(main_graphics_memory + x + w + ((ny >> 3) << 7)) |= (1 << (ny & 7));
}
h++;
nc >>= 1;
} while (h < 7);
w++;
} while (w < 5);
}

static void ruyi_draw_black_number(uint32_t x, uint32_t y, const uint8_t *bitmap)
{
uint32_t w = 0;
uint32_t h = 0;
uint32_t ny = 0;
uint8_t nc = 0;
do
{
nc = *(bitmap + w);
h = 0;
do
{
if (nc & 0x01)
{
ny = y + h;
*(main_graphics_memory + x + w + ((ny >> 3) << 7)) &= ~(1 << (ny & 7));
}
h++;
nc >>= 1;
} while (h < 7);
w++;
} while (w < 5);
}

static void ruyi_print_number(uint32_t x, uint32_t y, uint32_t color, uint32_t number)
{
uint8_t num_value[8];
uint32_t num_count = 0;
uint32_t num_rule = number < 10 ? 0 : 1;
switch (num_rule)
{
case 0:
switch (color)
{
case RUYI_COLOR_BLACK:
ruyi_draw_black_number(x, y, *(NUMBER_FONTS + number));
break;
case RUYI_COLOR_WHITE:
ruyi_draw_white_number(x, y, *(NUMBER_FONTS + number));
break;
}
break;
case 1:
do
{
num_value[num_count++] = number % 10;
number = ((uint64_t) RUYI_DIV_OPTIMIZATION * number) >> 32;
} while (number);
switch (color)
{
case RUYI_COLOR_BLACK:
while (num_count–)
{
ruyi_draw_black_number(x, y, *(NUMBER_FONTS + *(num_value + num_count)));
x += 6;
}
break;
case RUYI_COLOR_WHITE:
while (num_count–)
{
ruyi_draw_white_number(x, y, *(NUMBER_FONTS + *(num_value + num_count)));
x += 6;
}
break;
}
break;
}
}

static void ruyi_draw_white_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
uint32_t rx = 0;
uint32_t py = 0;
uint32_t ry = 0;
do
{
rx = 0;
do
{
py = y + ry;
*(main_graphics_memory + x + rx + ((py >> 3) << 7)) |= (1 << (py & 7));
rx++;
} while (rx < w);
ry++;
} while (ry < h);
}

static void ruyi_draw_white_bitmap(uint32_t x, uint32_t y, uint32_t w, uint32_t h, const uint8_t *bitmap)
{
uint32_t px = 0;
uint32_t sy = 0;
uint32_t py = 0;
uint32_t bt = 0;
uint32_t bn = (w + 7) >> 3;
uint8_t bp = 0;
do
{
if (py > 0)
{
bt += bn;
}
px = 0;
do
{
bp = px & 7 ? bp << 1 : pgm_read_byte(bitmap + bt + (px >> 3));
if (bp & 0x80)
{
sy = y + py;
*(main_graphics_memory + x + px + ((sy >> 3) << 7)) |= (1 << (sy & 7));
}
px++;
} while (px < w);
py++;
} while (py < h);
}

/**
static void ruyi_draw_block_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
uint32_t rx = 0;
uint32_t py = 0;
uint32_t ry = 0;
do
{
rx = 0;
do
{
py = y + ry;
*(main_graphics_memory + x + rx + ((py >> 3) << 7)) &= ~(1 << (py & 7));
rx++;
} while (rx < w);
ry++;
} while (ry < h);
}

static void ruyi_draw_black_bitmap(uint32_t x, uint32_t y, uint32_t w, uint32_t h, const uint8_t *bitmap)
{
uint32_t px = 0;
uint32_t sy = 0;
uint32_t py = 0;
uint32_t bt = 0;
uint32_t bn = (w + 7) >> 3;
uint8_t bp = 0;
do
{
if (py > 0)
{
bt += bn;
}
px = 0;
do
{
bp = px & 7 ? bp << 1 : pgm_read_byte(bitmap + bt + (px >> 3));
if (bp & 0x80)
{
sy = y + py;
*(g_mem + x + px + ((sy >> 3) << 7)) &= ~(1 << (sy & 7));
}
px++;
}
while (px < w);
py++;
}
while (py < h);
}
**/

static void ruyi_screen_command(uint8_t command)
{
Wire.beginTransmission(RUYI_IIC_ADDRESS);
Wire.write(RUYI_IIC_CO_DC);
delayMicroseconds(1000); /** If using the RTL8722DM or RTL8720DN development board, this line of delay is not required. **/
Wire.write(command);
Wire.endTransmission();
}

static void ruyi_screen_commandlist(uint8_t data, uint32_t size)
{
Wire.beginTransmission(RUYI_IIC_ADDRESS);
Wire.write(RUYI_IIC_CO_DC);
delayMicroseconds(1000); /
* If using the RTL8722DM or RTL8720DN development board, this line of delay is not required. **/
uint32_t c_count = 1;
while (size–)
{
if (c_count >= RUYI_IIC_DATA_LENGTH)
{
Wire.endTransmission();
Wire.beginTransmission(RUYI_IIC_ADDRESS);
Wire.write(RUYI_IIC_CO_DC);
c_count = 1;
}
Wire.write(pgm_read_byte(data++));
c_count++;
}
Wire.endTransmission();
}

static void ruyi_main_display()
{
ruyi_screen_commandlist(command_list_1, 5);
ruyi_screen_command(0x7F);
Wire.beginTransmission(RUYI_IIC_ADDRESS);
Wire.write(0x40);
delayMicroseconds(3600); /** If using the RTL8722DM or RTL8720DN development board, this line of delay is not required. */
uint32_t b_count = 0;
uint32_t s_count = 1;
uint8_t s_byte = NULL;
do
{
if (s_count >= RUYI_IIC_DATA_LENGTH)
{
Wire.endTransmission();
Wire.beginTransmission(RUYI_IIC_ADDRESS);
Wire.write(0x40);
delayMicroseconds(3600); /
If using the RTL8722DM or RTL8720DN development board, this line of delay is not required. **/
s_count = 1;
}
s_byte = main_graphics_memory + b_count;
Wire.write(*s_byte);
*s_byte = 0;
b_count++;
s_count++;
} while (b_count < RUYI_GRAPHICS_MEMORY);
Wire.endTransmission();
}

static void ruyi_screen_init()
{
memset(main_graphics_memory, 0, RUYI_GRAPHICS_MEMORY);
Wire.begin();
Wire.setClock(RUYI_IIC_CLOCK);
delay(10);
ruyi_screen_commandlist(command_list_2, 4);
ruyi_screen_command(0x3F);
ruyi_screen_commandlist(command_list_3, 4);
ruyi_screen_command(0x14);
ruyi_screen_commandlist(command_list_4, 4);
ruyi_screen_command(0xDA);
ruyi_screen_command(0x12);
ruyi_screen_command(0x81);
ruyi_screen_command(0xCF);
ruyi_screen_command(0xD9);
ruyi_screen_command(0xF1);
ruyi_screen_commandlist(command_list_5, 6);
}

void setup()
{
Serial.begin(115200);
while (!Serial)
{
;
}
ruyi_screen_init();
delay(10);
ruyi_draw_white_bitmap(49, 17, 29, 29, BUDDHA_BITMAP);
ruyi_main_display();
delay(3000);
uint32_t test1 = 1234567890;
uint32_t test2 = 99999999;
uint32_t i;
for (i = 0; i < test2; i++)
{
ruyi_print_number(35, 30, RUYI_COLOR_WHITE, test1);
ruyi_draw_white_rect(2, 2, 120, 20);
ruyi_print_number(35, 8, RUYI_COLOR_BLACK, i);
ruyi_print_number(35, 56, RUYI_COLOR_WHITE, test2 - i);
ruyi_main_display();
}
}

void loop()
{
/** Nothing… **/
}
AMB82_OLED_TEST.7z (2.2 KB)

而另外一個問題,就是使用相同的代碼,在之前的RTL8722DM上,可以打開混雜模式promiscuous mode,可以callback回調到所有類型的數據包,而在AMB82-MINI上,只能回調到信標幀、探測請求幀、數據幀,沒有其它類型數據包,這是什麽原因?怎麽解決?我是參考RTL8722DM的SDK目錄下的文件 :
realtek\hardware\AmebaD\3.x.x\system\component\common\api\wifi\wifi_promisc.c
以及Github上的某項目:GitHub - alexus2033/RTL8720-Sniffer: Presence detection using RTL8720DN 2.4G/5G Dual Bands Wifi Module

1 Like