mirror of
https://github.com/sipeed/Maixduino.git
synced 2026-03-03 00:53:59 +01:00
add KPU and mobilenet demo, fix LCD bug
This commit is contained in:
@@ -36,7 +36,7 @@ static const int resolution[][2] = {
|
||||
{1600, 1200}, /* UXGA */
|
||||
};
|
||||
|
||||
Camera::Camera(framesize_t frameSize = FRAMESIZE_QVGA, pixformat_t pixFormat = PIXFORMAT_RGB565)
|
||||
Camera::Camera(framesize_t frameSize, pixformat_t pixFormat)
|
||||
{
|
||||
_frameSize = frameSize;
|
||||
_pixFormat = pixFormat;
|
||||
@@ -44,6 +44,14 @@ Camera::Camera(framesize_t frameSize = FRAMESIZE_QVGA, pixformat_t pixFormat = P
|
||||
_height = resolution[frameSize][1];
|
||||
}
|
||||
|
||||
Camera::Camera(int16_t width, uint16_t height, pixformat_t pixFormat)
|
||||
{
|
||||
_frameSize = FRAMESIZE_CUSTOM;
|
||||
_pixFormat = pixFormat;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
{
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ typedef enum {
|
||||
FRAMESIZE_SVGA, // 800x600
|
||||
FRAMESIZE_SXGA, // 1280x1024
|
||||
FRAMESIZE_UXGA, // 1600x1200
|
||||
FRAMESIZE_CUSTOM,
|
||||
} framesize_t;
|
||||
|
||||
|
||||
@@ -51,6 +52,7 @@ class Camera{
|
||||
|
||||
public:
|
||||
Camera(framesize_t frameSize, pixformat_t pixFormat);
|
||||
Camera(int16_t width, uint16_t height, pixformat_t pixFormat);
|
||||
~Camera();
|
||||
virtual bool begin( ) = 0;
|
||||
virtual void end() = 0;
|
||||
@@ -64,8 +66,16 @@ public:
|
||||
* If pixels format is RGB565: return RGB565 pixels with every uint16_t one pixel, e.g. RED: 0xF800
|
||||
*/
|
||||
virtual uint8_t* snapshot() = 0;
|
||||
virtual uint8_t* getRGB565(){ return 0; };
|
||||
virtual uint8_t* getRGB888(){ return 0; };
|
||||
/**
|
||||
* @return pixels with RGB565 format, every uint16_t one pixel, e.g. RED: 0xF800, so two pixels: {0xF800, 0xF800}
|
||||
*/
|
||||
virtual uint16_t* getRGB565(){ return nullptr; };
|
||||
/**
|
||||
*
|
||||
* @return pixels with RGB888 format, for n pixels: {{R0,R1,...,Rn-1,},{G0,G1,...,Gn-1},{B0,B1,...,Bn-1}}
|
||||
* e.g. two RED pixel: {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}
|
||||
*/
|
||||
virtual uint8_t* getRGB888(){ return nullptr; };
|
||||
virtual void setRotaion(uint8_t rotation) = 0;
|
||||
virtual void setInvert(bool invert) = 0;
|
||||
|
||||
|
||||
208
libraries/KPU/examples/mobilenet_v1/MBNet_1000.cpp
Normal file
208
libraries/KPU/examples/mobilenet_v1/MBNet_1000.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* @file MBNet_1000.cpp
|
||||
* @brief Detect object type
|
||||
* @author Neucrack@sipeed.com
|
||||
*/
|
||||
|
||||
|
||||
#include "MBNet_1000.h"
|
||||
#include "names.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
|
||||
MBNet_1000::MBNet_1000(KPUClass& kpu, Sipeed_ST7789& lcd, Sipeed_OV2640& camera)
|
||||
:_kpu(kpu),_lcd(lcd), _camera(camera),
|
||||
_count(0), _result(nullptr)
|
||||
{
|
||||
_names = mbnet_label_name;
|
||||
memset(_statistics, 0, sizeof(_statistics));
|
||||
}
|
||||
|
||||
MBNet_1000::~MBNet_1000()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
int MBNet_1000::begin(const char* kmodel_name)
|
||||
{
|
||||
File myFile;
|
||||
if(!_camera.begin())
|
||||
return -1;
|
||||
if(!_lcd.begin(15000000, COLOR_RED))
|
||||
return -2;
|
||||
_camera.run(true);
|
||||
|
||||
if (!SD.begin())
|
||||
return -3;
|
||||
|
||||
myFile = SD.open(kmodel_name);
|
||||
if (!myFile)
|
||||
return -4;
|
||||
uint32_t fSize = myFile.size();
|
||||
_lcd.setTextSize(2);
|
||||
_lcd.setTextColor(COLOR_WHITE);
|
||||
_lcd.setCursor(100,100);
|
||||
_lcd.print("Loading ... ");
|
||||
long ret = myFile.read(_model, fSize);
|
||||
myFile.close();
|
||||
if(ret != fSize)
|
||||
return -5;
|
||||
|
||||
if(_kpu.begin(_model) != 0)
|
||||
return -6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MBNet_1000::detect()
|
||||
{
|
||||
uint8_t* img;
|
||||
uint8_t* img888;
|
||||
|
||||
img = _camera.snapshot();
|
||||
if(img == nullptr || img==0)
|
||||
return -1;
|
||||
img888 = _camera.getRGB888();
|
||||
if(_kpu.forward(img888) != 0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
while( !_kpu.isForwardOk() );
|
||||
if( _kpu.getResult((uint8_t**)&_result, &_count) != 0)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MBNet_1000::show()
|
||||
{
|
||||
float prob;
|
||||
const char* name;
|
||||
uint8_t i, j;
|
||||
uint16_t* img;
|
||||
|
||||
_count /= sizeof(float);
|
||||
label_init();
|
||||
label_sort();
|
||||
|
||||
for(j=0; j<STATISTICS_NUM; ++j)
|
||||
_statistics[j].updated = false;
|
||||
for ( i = 0; i < 5; i++)
|
||||
{
|
||||
label_get(i, &prob, &name);
|
||||
for(j=0; j<STATISTICS_NUM; ++j)
|
||||
{
|
||||
if(_statistics[j].name == NULL)
|
||||
{
|
||||
_statistics[j].name = name;
|
||||
_statistics[j].sum = prob;
|
||||
_statistics[j].updated = true;
|
||||
break;
|
||||
}
|
||||
else if( _statistics[j].name == name )
|
||||
{
|
||||
_statistics[j].sum += prob;
|
||||
_statistics[j].updated = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
if( j == STATISTICS_NUM)
|
||||
{
|
||||
float min = _statistics[0].sum;
|
||||
j = 0;
|
||||
for(i=1; i<STATISTICS_NUM; ++i)
|
||||
{
|
||||
if(_statistics[i].name)
|
||||
{
|
||||
if(_statistics[i].sum <= min)
|
||||
{
|
||||
min = _statistics[i].sum;
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
_statistics[j].name = name;
|
||||
_statistics[j].sum = prob;
|
||||
_statistics[j].updated = true;
|
||||
}
|
||||
}
|
||||
float max = _statistics[0].sum;
|
||||
float second = 0;
|
||||
uint8_t index1=0, index2 = 0;
|
||||
for(i=0; i<STATISTICS_NUM; ++i)
|
||||
{
|
||||
if(_statistics[i].name)
|
||||
{
|
||||
if(_statistics[i].sum > max)
|
||||
{
|
||||
max = _statistics[i].sum;
|
||||
index1 = i;
|
||||
}
|
||||
else if(_statistics[i].sum > second && _statistics[i].sum<max)
|
||||
{
|
||||
index2 = i;
|
||||
}
|
||||
}
|
||||
if( !_statistics[i].updated )
|
||||
{
|
||||
float tmp = _statistics[i].sum - _statistics[i].sum*2/5;
|
||||
if( tmp < 0)
|
||||
tmp = 0;
|
||||
_statistics[i].sum = tmp;
|
||||
}
|
||||
}
|
||||
img = _camera.getRGB565();
|
||||
_lcd.fillRect(224,0, _lcd.width()-224, _lcd.height(), COLOR_RED);
|
||||
_lcd.drawImage(0, 0, _camera.width(), _camera.height(), img);
|
||||
_lcd.setTextSize(2);
|
||||
_lcd.setTextColor(COLOR_WHITE);
|
||||
_lcd.setCursor(0,0);
|
||||
_lcd.println(_statistics[index1].name);
|
||||
_lcd.println("-----");
|
||||
_lcd.println(_statistics[index2].name);
|
||||
// _lcd.println("=======");
|
||||
// _lcd.println(_names[_index[0]]);
|
||||
// _lcd.println(_names[_index[1]]);
|
||||
// _lcd.println(_names[_index[2]]);
|
||||
// _lcd.println(_names[_index[3]]);
|
||||
// _lcd.println(_names[_index[4]]);
|
||||
}
|
||||
|
||||
|
||||
void MBNet_1000::label_init( )
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < _count; i++)
|
||||
_index[i] = i;
|
||||
}
|
||||
|
||||
void MBNet_1000::label_sort(void)
|
||||
{
|
||||
int i,j;
|
||||
float tmp_prob;
|
||||
uint16_t tmp_index;
|
||||
for(j=0; j<_count; j++)
|
||||
for(i=0; i<_count-1-j; i++)
|
||||
if(_result[i]<_result[i+1])
|
||||
{
|
||||
tmp_prob=_result[i];
|
||||
_result[i]=_result[i+1];
|
||||
_result[i+1]=tmp_prob;
|
||||
|
||||
tmp_index=_index[i];
|
||||
_index[i]=_index[i+1];
|
||||
_index[i+1]=tmp_index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MBNet_1000::label_get(uint16_t index, float* prob, const char** name)
|
||||
{
|
||||
*prob = _result[index];
|
||||
*name = _names[_index[index]];
|
||||
}
|
||||
|
||||
53
libraries/KPU/examples/mobilenet_v1/MBNet_1000.h
Normal file
53
libraries/KPU/examples/mobilenet_v1/MBNet_1000.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @file MBNet_1000.h
|
||||
* @brief Detect object type
|
||||
* @author Neucrack@sipeed.com
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MBNET_1000_H
|
||||
#define __MBNET_1000_H
|
||||
|
||||
#include "Sipeed_OV2640.h"
|
||||
#include "Sipeed_ST7789.h"
|
||||
#include <SD.h>
|
||||
#include <KPU.h>
|
||||
|
||||
#define KMODEL_SIZE (4220 * 1024)
|
||||
#define STATISTICS_NUM 5
|
||||
|
||||
typedef struct{
|
||||
const char* name;
|
||||
float sum;
|
||||
bool updated;
|
||||
} statistics_t;
|
||||
|
||||
|
||||
class MBNet_1000{
|
||||
|
||||
public:
|
||||
MBNet_1000(KPUClass& kpu, Sipeed_ST7789& lcd, Sipeed_OV2640& camera);
|
||||
~MBNet_1000();
|
||||
int begin(const char* kmodel_name);
|
||||
int detect();
|
||||
void show();
|
||||
const char** _names;
|
||||
|
||||
private:
|
||||
KPUClass& _kpu;
|
||||
Sipeed_ST7789& _lcd;
|
||||
Sipeed_OV2640& _camera;
|
||||
uint8_t _model[KMODEL_SIZE] __attribute__((aligned(128)));
|
||||
size_t _count;
|
||||
statistics_t _statistics[STATISTICS_NUM];
|
||||
float* _result;
|
||||
uint16_t _index[1000];
|
||||
|
||||
void label_init();
|
||||
void label_get(uint16_t index, float* prob, const char** name);
|
||||
void label_sort(void);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
54
libraries/KPU/examples/mobilenet_v1/mobilenet_v1.ino
Normal file
54
libraries/KPU/examples/mobilenet_v1/mobilenet_v1.ino
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Download model here:
|
||||
* http://dl.sipeed.com/MAIX/MaixPy/model/mobilenet_0x300000.kfpkg
|
||||
* Unpack it(zip format), get m.kmodel, change name to a short name "m" for example,
|
||||
* put it in SD card at root path
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Sipeed_OV2640.h>
|
||||
#include <Sipeed_ST7789.h>
|
||||
#include "MBNet_1000.h"
|
||||
|
||||
|
||||
SPIClass spi_(SPI0); // MUST be SPI0 for Maix series on board LCD
|
||||
Sipeed_ST7789 lcd(320, 240, spi_);
|
||||
Sipeed_OV2640 camera(224, 224, PIXFORMAT_RGB565);
|
||||
KPUClass KPU;
|
||||
MBNet_1000 mbnet(KPU, lcd, camera);
|
||||
|
||||
const char* kmodel_name = "m";
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for native USB port only
|
||||
}
|
||||
|
||||
Serial.println("init mobile net, load kmodel from SD card, it may takes a long time");
|
||||
if( mbnet.begin(kmodel_name) != 0)
|
||||
{
|
||||
Serial.println("mobile net init fail");
|
||||
while(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if(mbnet.detect() != 0)
|
||||
{
|
||||
Serial.println("detect object fail");
|
||||
return;
|
||||
}
|
||||
mbnet.show();
|
||||
}
|
||||
|
||||
1001
libraries/KPU/examples/mobilenet_v1/names.cpp
Normal file
1001
libraries/KPU/examples/mobilenet_v1/names.cpp
Normal file
File diff suppressed because it is too large
Load Diff
7
libraries/KPU/examples/mobilenet_v1/names.h
Normal file
7
libraries/KPU/examples/mobilenet_v1/names.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef __MBNET_NAMES_H
|
||||
#define __MBNET_NAMES_H
|
||||
|
||||
extern const char* mbnet_label_name[];
|
||||
|
||||
#endif
|
||||
|
||||
26
libraries/KPU/keywords.txt
Normal file
26
libraries/KPU/keywords.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map SD
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
KPUClass KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
begin KEYWORD2
|
||||
end KEYWORD2
|
||||
forward KEYWORD2
|
||||
isForwardOk KEYWORD2
|
||||
getResult KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
KPU_ERROR_BUSY LITERAL1
|
||||
KPU_ERROR_BAD_MODEL LITERAL1
|
||||
KPU_ERROR_MODEL_VERSION LITERAL1
|
||||
KPU_ERROR_NONE LITERAL1
|
||||
9
libraries/KPU/library.properties
Normal file
9
libraries/KPU/library.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
name=KPU
|
||||
version=1.0.0
|
||||
author= Neucrack Sipeed
|
||||
maintainer=Sipeed <support@sipeed.com>
|
||||
sentence=KPU API of k210
|
||||
paragraph=KPU API of k210
|
||||
category=Other
|
||||
url=
|
||||
architectures=k210
|
||||
74
libraries/KPU/src/KPU.cpp
Normal file
74
libraries/KPU/src/KPU.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
|
||||
#include "KPU.h"
|
||||
#include "sysctl.h"
|
||||
|
||||
|
||||
#define AI_STATUS_IDLE 0
|
||||
#define AI_STATUS_BUSY 1
|
||||
#define AI_STATUS_OK 2
|
||||
|
||||
|
||||
static volatile uint32_t g_ai_done_flag = AI_STATUS_IDLE;
|
||||
|
||||
KPUClass::KPUClass()
|
||||
:_flagGotResult(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KPUClass::~KPUClass()
|
||||
{
|
||||
end();
|
||||
}
|
||||
|
||||
int KPUClass::begin(uint8_t* model)
|
||||
{
|
||||
sysctl_clock_enable(SYSCTL_CLOCK_AI);
|
||||
if (kpu_load_kmodel(&_task, model) != 0)
|
||||
return KPU_ERROR_BAD_MODEL;
|
||||
return KPU_ERROR_NONE;
|
||||
}
|
||||
|
||||
void KPUClass::end()
|
||||
{
|
||||
sysctl_clock_disable(SYSCTL_CLOCK_AI);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static void ai_done(void* userdata)
|
||||
{
|
||||
bool* user_used = (bool*)userdata;
|
||||
g_ai_done_flag = AI_STATUS_OK;
|
||||
*user_used = false;
|
||||
}
|
||||
}
|
||||
|
||||
int KPUClass::forward(uint8_t* imgSrc, uint8_t dmaCh)
|
||||
{
|
||||
if(g_ai_done_flag == AI_STATUS_BUSY)
|
||||
return KPU_ERROR_BUSY;
|
||||
g_ai_done_flag = AI_STATUS_BUSY;
|
||||
if (kpu_run_kmodel(&_task, imgSrc, (dmac_channel_number_t)dmaCh, ai_done, (void*)&_flagGotResult) != 0)
|
||||
{
|
||||
g_ai_done_flag = AI_STATUS_IDLE;
|
||||
return KPU_ERROR_BAD_MODEL;
|
||||
}
|
||||
return KPU_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool KPUClass::isForwardOk()
|
||||
{
|
||||
return g_ai_done_flag==AI_STATUS_OK;
|
||||
}
|
||||
|
||||
int KPUClass::getResult(uint8_t**data, size_t* count, uint32_t startIndex )
|
||||
{
|
||||
_flagGotResult = true;
|
||||
kpu_get_output(&_task, startIndex, data, count);
|
||||
return KPU_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
42
libraries/KPU/src/KPU.h
Normal file
42
libraries/KPU/src/KPU.h
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
#ifndef __MOBILENET_V1_H
|
||||
#define __MOBILENET_V1_H
|
||||
|
||||
extern "C" {
|
||||
#include "kpu.h"
|
||||
}
|
||||
|
||||
typedef enum{
|
||||
KPU_ERROR_BUSY = -3,
|
||||
KPU_ERROR_BAD_MODEL = -2,
|
||||
KPU_ERROR_MODEL_VERSION = -1,
|
||||
KPU_ERROR_NONE = 0,
|
||||
} KPU_Error_t;
|
||||
|
||||
|
||||
class KPUClass{
|
||||
|
||||
public:
|
||||
KPUClass();
|
||||
~KPUClass();
|
||||
int begin(uint8_t* model);
|
||||
void end();
|
||||
/**
|
||||
* @param imgSrc RGB888 image source
|
||||
* @param dmaCh [0,5)
|
||||
*/
|
||||
int forward(uint8_t* imgSrc, uint8_t dmaCh=0);
|
||||
bool isForwardOk();
|
||||
int getResult(uint8_t**data, size_t* count, uint32_t startIndex = 0);
|
||||
|
||||
|
||||
private:
|
||||
kpu_model_context_t _task;
|
||||
bool _flagGotResult;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -95,6 +95,22 @@ int File::read(void *buf, uint16_t nbyte) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long File::read(void *buf, uint32_t nbyte) {
|
||||
if (!_file)
|
||||
return 0;
|
||||
uint32_t bytesToRead = nbyte;
|
||||
uint16_t ret, readBytesOnece;
|
||||
while(bytesToRead)
|
||||
{
|
||||
readBytesOnece = (bytesToRead>65000) ? 65000 : bytesToRead;
|
||||
ret = (uint16_t)_file->read(buf+(nbyte-bytesToRead), readBytesOnece);
|
||||
if(ret == 0xffff)
|
||||
return -1;
|
||||
bytesToRead -= ret;
|
||||
}
|
||||
return nbyte;
|
||||
}
|
||||
|
||||
int File::available() {
|
||||
if (! _file) return 0;
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
virtual int available();
|
||||
virtual void flush();
|
||||
int read(void *buf, uint16_t nbyte);
|
||||
long read(void *buf, uint32_t nbyte);
|
||||
boolean seek(uint32_t pos);
|
||||
uint32_t position();
|
||||
uint32_t size();
|
||||
|
||||
@@ -606,6 +606,19 @@ _id(0)
|
||||
configASSERT(pixFormat == PIXFORMAT_RGB565 || pixFormat==PIXFORMAT_YUV422);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Sipeed_OV2640::Sipeed_OV2640(uint16_t width, uint16_t height, pixformat_t pixFormat)
|
||||
:Camera(width, height, pixFormat),
|
||||
_dataBuffer(NULL), _aiBuffer(NULL),
|
||||
_resetPoliraty(ACTIVE_HIGH), _pwdnPoliraty(ACTIVE_HIGH),
|
||||
_slaveAddr(0x00),
|
||||
_id(0)
|
||||
{
|
||||
configASSERT(pixFormat == PIXFORMAT_RGB565 || pixFormat==PIXFORMAT_YUV422);
|
||||
}
|
||||
|
||||
|
||||
Sipeed_OV2640::~Sipeed_OV2640()
|
||||
{
|
||||
end();
|
||||
|
||||
@@ -37,6 +37,7 @@ class Sipeed_OV2640 : public Camera{
|
||||
|
||||
public:
|
||||
Sipeed_OV2640(framesize_t frameSize = FRAMESIZE_QVGA, pixformat_t pixFormat = PIXFORMAT_RGB565);
|
||||
Sipeed_OV2640(uint16_t width, uint16_t height, pixformat_t pixFormat = PIXFORMAT_RGB565);
|
||||
~Sipeed_OV2640();
|
||||
|
||||
virtual bool begin();
|
||||
@@ -51,6 +52,8 @@ public:
|
||||
* If pixels format is RGB565: return RGB565 pixels with every uint16_t one pixel, e.g. RED: 0xF800
|
||||
*/
|
||||
virtual uint8_t* snapshot();
|
||||
virtual uint16_t* getRGB565(){ return (uint16_t*)_dataBuffer; };
|
||||
virtual uint8_t* getRGB888(){ return _aiBuffer; };
|
||||
virtual void setRotaion(uint8_t rotation);
|
||||
virtual void setInvert(bool invert);
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ void lcd_set_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
|
||||
void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
lcd_set_area(x, y, x, y);
|
||||
tft_write_byte((uint8_t*)&color, 2);
|
||||
tft_write_half(&color, 1);
|
||||
}
|
||||
|
||||
void lcd_clear(uint16_t color)
|
||||
@@ -204,13 +204,13 @@ void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint
|
||||
*p++ = data;
|
||||
|
||||
lcd_set_area(x1, y1, x2, y1 + width - 1);
|
||||
tft_write_byte((uint8_t*)data_buf, ((x2 - x1 + 1) * width + 1) * 2);
|
||||
tft_write_word(data_buf, ((x2 - x1 + 1) * width + 1) / 2);
|
||||
lcd_set_area(x1, y2 - width + 1, x2, y2);
|
||||
tft_write_byte((uint8_t*)data_buf, ((x2 - x1 + 1) * width + 1) * 2);
|
||||
tft_write_word(data_buf, ((x2 - x1 + 1) * width + 1) / 2);
|
||||
lcd_set_area(x1, y1, x1 + width - 1, y2);
|
||||
tft_write_byte((uint8_t*)data_buf, ((y2 - y1 + 1) * width + 1) * 2);
|
||||
tft_write_word(data_buf, ((y2 - y1 + 1) * width + 1) / 2);
|
||||
lcd_set_area(x2 - width + 1, y1, x2, y2);
|
||||
tft_write_byte((uint8_t*)data_buf, ((y2 - y1 + 1) * width + 1) * 2);
|
||||
tft_write_word(data_buf, ((y2 - y1 + 1) * width + 1) / 2);
|
||||
}
|
||||
|
||||
#define SWAP_16(x) ((x >> 8 & 0xff) | (x << 8))
|
||||
|
||||
@@ -73,7 +73,7 @@ void tft_write_byte(uint8_t *data_buf, uint32_t length)
|
||||
{
|
||||
set_dcx_data();
|
||||
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
|
||||
spi_init_non_standard(g_spi_num, 0 /*instrction length*/, 8 /*address length*/, 0 /*wait cycles*/,
|
||||
spi_init_non_standard(g_spi_num, 8 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/,
|
||||
SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
|
||||
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, data_buf, length, SPI_TRANS_CHAR);
|
||||
}
|
||||
@@ -82,7 +82,7 @@ void tft_write_half(uint16_t *data_buf, uint32_t length)
|
||||
{
|
||||
set_dcx_data();
|
||||
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0);
|
||||
spi_init_non_standard(g_spi_num, 0 /*instrction length*/, 16 /*address length*/, 0 /*wait cycles*/,
|
||||
spi_init_non_standard(g_spi_num, 16 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/,
|
||||
SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
|
||||
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, data_buf, length, SPI_TRANS_SHORT);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user