Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources

This commit is contained in:
2026-07-06 11:30:13 +08:00
commit e76462eeb7
3451 changed files with 1415300 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
#ifndef _PRINTER_H_
#define _PRINTER_H_
void printer_thread_init();
#endif

12290
sdk/app/printer/printer_demo.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,896 @@
#include "basic_include.h"
#include "hal/dvp.h"
#include "hal/vpp.h"
#include "hal/adc.h"
#include "hal/spi.h"
#include "hal/pwm.h"
#include "hal/timer_device.h"
#include "gpio/hggpio_v4_hw.h"
#if PRINTER_EN
/*
config.cfg 文件引脚定义
//打印机的CLK、DATA引脚
PIN_SPI1_CLK = PB_11
PIN_SPI1_IO0 = PB_13
//步进电机引脚
PIN_SPI2_IO0 = PB_14
PIN_SPI2_IO1 = PB_15
PIN_SPI2_IO2 = PC_1
PIN_SPI2_IO3 = PC_0
*/
#define GPIOA ((struct hggpio_v4_hw *) GPIOA_BASE)
#define GPIOB ((struct hggpio_v4_hw *) GPIOB_BASE)
#define GPIOC ((struct hggpio_v4_hw *) GPIOC_BASE)
#define GPIOD ((struct hggpio_v4_hw *) GPIOD_BASE)
/*==================================打印机引脚定义==================================*/
#define MOTO_SLEEP_PIN PB_7 // LOW sleep , HIGH run
#define PRINTER_DATA_PIN PB_13
#define PRINTER_CLK_PIN PB_11
#define PRINTER_LATCH_PIN PB_8
#define PRINTER_TM_PIN PC_5
#define PRINTER_PSENSOR_PIN PA_0
#define PRINTER_STB_PIN PB_10
#define PRINTER_EN_PIN PA_7
#define PRINTER_DATA_PORT GPIOB
#define PRINTER_DATA_NUM 13
#define PRINTER_CLK_PORT GPIOB
#define PRINTER_CLK_NUM 11
#define PRINTER_STB_PORT GPIOB
#define PRINTER_STB_NUM 10
#define PRINTER_W 384
#define PRINTER_H 512
// HEAT_BYTES_PER_LINE 表示每行用于控制加热单元的字节数48 字节 * 8 位 = 384 点)
#define HEAT_BYTES_PER_LINE 48
/*====================================第一组 PWM====================================*/
#define SPI_SEND_EN 1 //使用SPI时序发送数据可控发送速率
#define STB_PIN_PWM_EN 0 //STB 使用PWM波形使能置1否则置0
#define SPI_MOTO_EN 1
#define SPI_MOTO_CLK 5000 //4000:12ms 5000:9.6ms
#define TEST_MOTO_BUF_COUNT 6
#define HEAT_TIMES_THRESHOLD 128
#define TOTAL_TICK 258 //打印每行调用printer_heat_transfer_data函数的次数
#define SPI_CLK_FREQ 5300000 //SPI时钟频率8M CLK脚高电平稳定时间约为50-60ns, 调整建议不大于8M频率越高加热时间越短
#define STB_PIN_PWM_PERIOD 1000
#define STB_PIN_PWM_DUTY 900 //改变PWM的占空比可以改变加热时长
#define PRINTER_DITHERING_EN 0 //半色调散点特效
#define PRINTER_TEST_PATTER_EN 1 //打印机测试模式
#if STB_PIN_PWM_EN
static struct hgpwm_v0 *moto_hgpwm = NULL;
#endif
static struct spi_device *spi0_dev = NULL;
static struct spi_device *spi1_dev = NULL;
static uint32_t current_heat_count = 0;
static uint8_t* halfstep_buf = NULL;
static uint8_t* halfstep_buf_cache = NULL;
static uint8_t* printer_buf = NULL;
static uint8_t* printer_buf_odd = NULL;
static uint8_t* printer_buf_even = NULL;
static volatile uint8_t last_ret = 0;
static uint8_t pre_heat_flag = 0;
static volatile uint8_t printer_done = 1;
volatile uint8 printer_action = 0;
volatile uint32_t printer_h = 0;
const unsigned char *printer_picture_addr;
static uint32_t printer_heat_transfer_data();
extern const unsigned char printer_demo[PRINTER_W * PRINTER_H]; //384 x 512 只包含Y数据的图片
static void printer_moto_delay(uint32_t n)
{
volatile uint32_t i=500*n;
while(i--)
{
}
}
static void printer_delay(uint32_t n)
{
volatile uint32_t i=20*n;
while(i--)
{
}
}
void printer_moto_enable(uint8_t en)
{
if(en)
{
gpio_set_val(MOTO_SLEEP_PIN,1);
printer_moto_delay(20);
}
else
{
gpio_set_val(MOTO_SLEEP_PIN,0);
}
}
int32_t get_printer_tm(){
uint32 vol = 0;
struct hgadc_v0* hgadc_tm = NULL;
printer_delay(100);
hgadc_tm = (struct hgadc_v0*)dev_get(HG_ADC0_DEVID);
adc_open((struct adc_device *)(hgadc_tm));
adc_add_channel((struct adc_device *)hgadc_tm, PRINTER_TM_PIN);
adc_get_value((struct adc_device *)hgadc_tm, PRINTER_TM_PIN, &vol);
os_printf("temperature:%d\r\n",vol);
return vol;
}
uint8_t is_paper_insert(){
return gpio_get_val(PRINTER_PSENSOR_PIN);
}
/*
半步驱动-低位在前
(1) A1:1 A2:1 B1:1 B2:0 0xEE
(2) A1:1 A2:0 B1:1 B2:0 0xAA
(3) A1:1 A2:0 B1:1 B2:1 0xBB
(4) A1:1 A2:0 B1:0 B2:1 0x99
(5) A1:1 A2:1 B1:0 B2:1 0xDD
(6) A1:0 A2:1 B1:0 B2:1 0x55
(7) A1:0 A2:1 B1:1 B2:1 0x77
(8) A1:0 A2:1 B1:1 B2:0 0x66
*/
void printer_get_four_halfstep(uint8 *halfstep_buf, uint32_t n)
{
static const uint8_t halfstep_table[8] = {0xEE, 0xAA, 0xBB, 0x99, 0xDD, 0x55, 0x77, 0x66};
static uint8_t current_step = 0;
int i = 0, j = 0;
int k = n / 4;
//调试打印会影响打印时间
// os_printf("halfstep_buf: ");
for (i = 0; i < 4; i++)
{
uint8_t index = (i + current_step) % 8;
for (j = 0; j < k; j++)
{
halfstep_buf[i*k+j] = halfstep_table[index];
}
// printf("%02X ", halfstep_buf[index]);
}
//最后1byte为0,用于hold住spi数据线为0
halfstep_buf[n] = 0;
// printf("%02X \n", halfstep_buf[n]);
current_step = (current_step + 4) % 8;
}
//中断处理的效率会影响加热时间
static void spi0_irq(uint32 irq, uint32 irq_data, uint32 param1, uint32 param2)
{
uint8_t *halfstep_buf = (uint8_t *)irq_data;
current_heat_count ++;
gpio_set_val(PRINTER_LATCH_PIN,0);
gpio_set_val(PRINTER_LATCH_PIN,1);
switch(last_ret)
{
//一帧图片打印结束
case 0:
#if STB_PIN_PWM_EN
pwm_ioctl((struct pwm_device *)moto_hgpwm,PWM_CHANNEL_4,PWM_IOCTL_CMD_SET_PERIOD_DUTY_IMMEDIATELY,STB_PIN_PWM_PERIOD,0);
#else
gpio_set_val(PRINTER_STB_PIN,0); //关加热
#endif
os_printf("kick moto spi done\n");
printer_get_four_halfstep(halfstep_buf, TEST_MOTO_BUF_COUNT*4);
printer_get_four_halfstep(halfstep_buf_cache, TEST_MOTO_BUF_COUNT*4);
spi_ioctl((struct spi_device*)spi1_dev, SPI_KICK_DMA_TX, (uint32)halfstep_buf, TEST_MOTO_BUF_COUNT*4+1);
spi_release_irq(spi0_dev,SPI_IRQ_FLAG_TX_DONE);
printer_done = 2;
break;
//加热期间spi传送数据
case 1:
last_ret = printer_heat_transfer_data();
break;
//一行打印结束,电机走四步
case 2:
#if STB_PIN_PWM_EN
pwm_ioctl((struct pwm_device *)moto_hgpwm,PWM_CHANNEL_4,PWM_IOCTL_CMD_SET_PERIOD_DUTY_IMMEDIATELY,STB_PIN_PWM_PERIOD,0);
#else
gpio_set_val(PRINTER_STB_PIN,0); //关加热
#endif
printer_get_four_halfstep(halfstep_buf, TEST_MOTO_BUF_COUNT*4);
spi_ioctl((struct spi_device*)spi1_dev, SPI_KICK_DMA_TX, (uint32)halfstep_buf, TEST_MOTO_BUF_COUNT*4+1);
spi_release_irq(spi0_dev,SPI_IRQ_FLAG_TX_DONE);
break;
default:
break;
};
if(current_heat_count >= HEAT_TIMES_THRESHOLD)
{
current_heat_count = 0;
}
}
static void spi1_irq(uint32 irq, uint32 irq_data, uint32 param1, uint32 param2)
{
static uint32_t moto_cycle_count = 250;
if (printer_done == 2) {
//加热打印结束,电机送纸部分
if(moto_cycle_count == 0) {
printer_done = 1;
moto_cycle_count = 250;
spi_close(spi1_dev);
} else {
if(moto_cycle_count % 2 == 0)
{
spi_ioctl((struct spi_device*)spi1_dev, SPI_KICK_DMA_TX, (uint32)halfstep_buf_cache, TEST_MOTO_BUF_COUNT*4);
}
else
{
spi_ioctl((struct spi_device*)spi1_dev, SPI_KICK_DMA_TX, (uint32)halfstep_buf, TEST_MOTO_BUF_COUNT*4);
}
moto_cycle_count--;
}
} else {
//行打印结束,电机走一行
#if STB_PIN_PWM_EN
pwm_ioctl((struct pwm_device *)moto_hgpwm,PWM_CHANNEL_4,PWM_IOCTL_CMD_SET_PERIOD_DUTY_IMMEDIATELY,STB_PIN_PWM_PERIOD,STB_PIN_PWM_DUTY);
#else
gpio_set_val(PRINTER_STB_PIN,1); //加热
#endif
spi_request_irq(spi0_dev, SPI_IRQ_FLAG_TX_DONE, spi0_irq, (uint32)halfstep_buf);
last_ret = printer_heat_transfer_data();
}
}
static void stb_timer_cb(uint32 cb_data, uint32 irq_flag)
{
//预加热结束
os_printf("stb timer callback\n");
#if STB_PIN_PWM_EN
pwm_ioctl((struct pwm_device *)moto_hgpwm,PWM_CHANNEL_4,PWM_IOCTL_CMD_SET_PERIOD_DUTY_IMMEDIATELY,STB_PIN_PWM_PERIOD,0);
#else
gpio_set_val(PRINTER_STB_PIN,0); //关加热
#endif
pre_heat_flag = 1;
}
static void* printer_stb_timer_open()
{
struct timer_device *stb_timer0 = (struct timer_device *)dev_get(HG_TIMER0_DEVID);
timer_device_open(stb_timer0, TIMER_TYPE_ONCE, 0);
os_printf("STB timer open\n");
return stb_timer0;
}
static void printer_stb_timer_close(void* stb_timer0)
{
timer_device_close((struct timer_device *)stb_timer0);
}
static void printer_stb_start(void* stb_timer0, uint32_t ms)
{
#if STB_PIN_PWM_EN
pwm_ioctl((struct pwm_device *)moto_hgpwm,PWM_CHANNEL_4,PWM_IOCTL_CMD_SET_PERIOD_DUTY_IMMEDIATELY,STB_PIN_PWM_PERIOD,STB_PIN_PWM_DUTY);
#else
gpio_set_val(PRINTER_STB_PIN,1); //加热
#endif
uint32_t sys_clk = system_clock_get();
timer_device_start((struct timer_device *)stb_timer0, ms*(sys_clk/1000), stb_timer_cb, 0); // cnt = ms * (240M/1000)
}
static void paper_io_init()
{
gpio_iomap_output(MOTO_SLEEP_PIN,GPIO_IOMAP_OUTPUT);
gpio_iomap_output(PRINTER_LATCH_PIN,GPIO_IOMAP_OUTPUT);
gpio_set_val(PRINTER_LATCH_PIN,1);
gpio_iomap_output(PRINTER_STB_PIN,GPIO_IOMAP_OUTPUT);
gpio_iomap_output(PRINTER_EN_PIN,GPIO_IOMAP_OUTPUT);
gpio_iomap_output(PRINTER_TM_PIN,GPIO_IOMAP_OUTPUT);
gpio_set_mode(PRINTER_PSENSOR_PIN, GPIO_PULL_NONE, GPIO_PULL_LEVEL_NONE);
gpio_iomap_input(PRINTER_PSENSOR_PIN,GPIO_IOMAP_INPUT);
//打印机数据输出spi0 一线模式
spi0_dev = (struct spi_device *)dev_get(HG_SPI1_DEVID);
spi_ioctl(spi0_dev,SPI_CFG_SET_NONE_CS,1,0);
spi_ioctl(spi0_dev,SPI_SET_LSB_FIRST,0,0);
spi_ioctl(spi0_dev,SPI_KICK_DMA_EN,0,0);
spi_open(spi0_dev,SPI_CLK_FREQ,SPI_MASTER_MODE,SPI_WIRE_SINGLE_MODE,SPI_CPOL_0_CPHA_0);
spi_release_irq((struct spi_device*)spi0_dev,SPI_IRQ_FLAG_TX_DONE | SPI_IRQ_FLAG_RX_DONE);
//步进电机时序spi1 四线模式
spi1_dev = (struct spi_device *)dev_get(HG_SPI2_DEVID);
spi_ioctl(spi1_dev,SPI_CFG_SET_NONE_CS,1,0);
spi_ioctl(spi1_dev,SPI_SET_LSB_FIRST,1,0);
spi_open(spi1_dev,SPI_MOTO_CLK,SPI_MASTER_MODE,SPI_WIRE_QUAD_MODE,SPI_CPOL_0_CPHA_1);
spi_request_irq((struct spi_device *)spi1_dev, SPI_IRQ_FLAG_TX_DONE, spi1_irq, (uint32)halfstep_buf);
#if STB_PIN_PWM_EN
//STB加热采用PWM输出
moto_hgpwm = (struct hgpwm_v0 *)dev_get(HG_PWM0_DEVID);
pwm_init((struct pwm_device *)moto_hgpwm, PWM_CHANNEL_4, STB_PIN_PWM_PERIOD, 0);
pwm_start((struct pwm_device *)moto_hgpwm, PWM_CHANNEL_4);
#endif
}
static void paper_io_deinit()
{
struct hgadc_v0* hgadc_tm = NULL;
hgadc_tm = (struct hgadc_v0*)dev_get(HG_ADC0_DEVID);
adc_close((struct adc_device *)(hgadc_tm));
adc_delete_channel((struct adc_device *)(hgadc_tm),PRINTER_TM_PIN);
#if STB_PIN_PWM_EN
pwm_deinit((struct pwm_device *)moto_hgpwm,PWM_CHANNEL_4);
#endif
spi_close(spi0_dev);
spi_close(spi1_dev);
}
static uint32_t printer_heat_transfer_data()
{
#define HOTTIME 1500
uint32_t itk = 0;
uint32_t jtk = 0;
static uint32_t i = 0;
static uint32_t j = 0;
static uint32_t tick = 0;
static uint32_t hot_time = 0;
static uint8_t half_s = 0;
static uint8_t hot_add = 0;
uint32 offset_h;
uint8_t *pt;
pt = printer_buf;
if (printer_h == PRINTER_H) {
tick = 2;
}
offset_h = (printer_h-1)*PRINTER_W;
if ((tick%2) == 0) {
#if STB_PIN_PWM_EN
pwm_ioctl((struct pwm_device *)moto_hgpwm,PWM_CHANNEL_4,PWM_IOCTL_CMD_SET_PERIOD_DUTY_IMMEDIATELY, STB_PIN_PWM_PERIOD, STB_PIN_PWM_DUTY); //加热
#else
PRINTER_STB_PORT->ODAT |= BIT(PRINTER_STB_NUM); //加热
#endif
if (hot_time > HOTTIME)
goto deal_end;
if (half_s) {
//偶数点
spi_ioctl((struct spi_device*)spi0_dev, SPI_KICK_DMA_TX, (uint32)printer_buf_even, HEAT_BYTES_PER_LINE);
os_memset(printer_buf_odd , 0, HEAT_BYTES_PER_LINE);
for(jtk = 0; jtk < HEAT_BYTES_PER_LINE; jtk++)
{
for(itk = 1 + i; itk < 8; itk+=2)
{
if ((pt[offset_h+jtk*8+itk]) > 0 && (1)) {
pt[offset_h+jtk*8+itk]--;
printer_buf_odd[jtk] |= (0x1 << (7-itk));
}
}
}
} else {
//奇数点
spi_ioctl((struct spi_device*)spi0_dev, SPI_KICK_DMA_TX, (uint32)printer_buf_odd, HEAT_BYTES_PER_LINE);
os_memset(printer_buf_even, 0, HEAT_BYTES_PER_LINE);
for(jtk = 0; jtk < HEAT_BYTES_PER_LINE; jtk++)
{
for(itk = 0 + j; itk < 8; itk+=2)
{
if ((pt[offset_h+jtk*8+itk]) > 0 && (1)) {
pt[offset_h+jtk*8+itk]--;
printer_buf_even[jtk] |= (0x1 << (7-itk));
}
}
}
}
half_s ^= BIT(0);
hot_add++;
}
deal_end:
if ((tick % TOTAL_TICK) == 2) {
printer_h--;
hot_time = 0;
if (printer_h == 0) {
return 0;
} else {
tick+=2;
hot_time++;
return 2;
}
}
tick+=2;
hot_time++;
return 1;
}
/**
* @brief 设置打印机的图片地址赋值给全局变量printer_picture_addr
*
* @param addr 传入的图片地址
* @return true
* @return false
*/
bool printer_set_picture_addr(const unsigned char* addr)
{
if(addr == NULL) {
os_printf("printer demo addr invaild!!! addr:%x\n",addr);
return 1;
}
printer_picture_addr = addr;
return 0;
}
/**
* @brief 打印机线程使能
*
* @return true
*/
bool printer_kick_start()
{
printer_action = 1;
return 0;
}
/**
* @brief 切换打印机与摄像头的使能
*
* @param printer_en 如果使能打印机、关闭摄像头则置1否则置0
*/
void printer_dvp_en_exchange(int printer_en)
{
#if DVP_EN
struct dvp_device *dvp_device = (struct dvp_device*)dev_get(HG_DVP_DEVID);
struct vpp_device *vpp_device = (struct vpp_device*)dev_get(HG_VPP_DEVID);
#endif
os_printf("%s %d\r\n",__FUNCTION__,printer_en);
//打印机使能
if(printer_en)
{
gpio_set_val(PRINTER_EN_PIN,1);
#if DVP_EN
gpio_iomap_output(PIN_DVP_PDN,GPIO_IOMAP_OUTPUT);
gpio_set_val(PIN_DVP_PDN,1);
dvp_close(dvp_device);
vpp_close(vpp_device);
#endif
}
//DVP使能
else {
gpio_set_val(PRINTER_EN_PIN, 0);
#if DVP_EN
bool csi_ret;
bool csi_cfg();
bool csi_open();
gpio_iomap_output(PIN_DVP_PDN,GPIO_IOMAP_OUTPUT);
gpio_set_val(PIN_DVP_PDN, 0);
#if SDH_I2C2_REUSE
uint32 sdhost_i2c2_exchange(int sdh_stop_en);
sdhost_i2c2_exchange(1);
#endif
csi_ret = csi_cfg();
if(csi_ret)
csi_open();
vpp_open(vpp_device);
#if SDH_I2C2_REUSE
sdhost_i2c2_exchange(0);
#endif
#endif
}
}
static unsigned char linearInterpolation(unsigned char* pline1, unsigned char* pline2, int channels,int u, int v)
{
int pm3 = u * v;
int pm2 = (u << 8) - pm3;
int pm1 = (v << 8) - pm3;
int pm0 = (1 << 16) - pm1 - pm2 - pm3;
unsigned char result = (unsigned char)(((pm0*pline1[0] + pm2 * pline1[channels] + pm1 * pline2[0] + pm3* pline2[channels]) >> 16)&0xff);
return result;
}
void zoomImg(unsigned char *psrc, int sw, int sh, int channels, unsigned char *pdst, int dw, int dh)
{
if (!psrc || !pdst) return;
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) return;
if (channels != 1 && channels != 3) return;
unsigned char *p = psrc,*q = pdst,*pt;
int srcBytesPerLine = sw * channels,dstBytesPerLine = dw * channels;
int srcy_16 = 0, v_8 = 0, srcx_16 = 0;
int stepw = (((sw - 1) << 16) / dw +1);
int steph = ((sh - 1) << 16) / dh + 1;
//int stepc = ((channels - 1) << 16)/channels + 1;
int i, j, m;
srcy_16 = 0;
for (j = 0; j < dh; j++)
{
v_8 = (srcy_16 & 0xFFFF) >> 8;
p = psrc + srcBytesPerLine * (srcy_16 >> 16);
srcx_16 = 0;
for (i = 0; i < dstBytesPerLine; i+=channels)
{
pt = &p[(srcx_16>>16)*channels];
for (m = 0; m < channels; m++) {
q[i+m] = linearInterpolation(&pt[m], &pt[m] + srcBytesPerLine, channels, (srcx_16 & 0xFFFF) >> 8, v_8);
}
srcx_16 += stepw;
}
srcy_16 += steph;
q += dstBytesPerLine;
}
}
void vga_to_paper_size(uint8_t *src, uint8_t* des)
{
uint16_t x=0,y=0;
zoomImg(src, 640, 480, 1, des, PRINTER_H, PRINTER_W);
for(y=0; y<PRINTER_W; y++)
{
for(x=0; x<PRINTER_H; x++)
{
src[(x+1)*PRINTER_W-1-y] = des[x+y*PRINTER_H];//90°
}
}
}
void enhanceContrast(uint8_t *image)
{
int minLevel = 63;
int maxLevel = 0;
for (int i = 0; i < PRINTER_W * PRINTER_H; i++) {
if (image[i] < minLevel) {
minLevel = image[i];
}
if (image[i] > maxLevel) {
maxLevel = image[i];
}
}
int dynamicRange = maxLevel - minLevel;
for (int i = 0; i < PRINTER_W * PRINTER_H; i++) {
image[i] = (image[i] - minLevel) * 63 / dynamicRange;
if (image[i] < 0) {
image[i] = 0;
}
if (image[i] > 63) {
image[i] = 63;
}
}
}
unsigned char restrain_int(int input)
{
if (input < 0x00) {
return 0x00;
}
if (input > 0xFF) {
return 0xFF;
}
return input;
}
//Floyd-Steinberg算法,该函数只适用于256灰阶图像
void dithering(uint8_t *image, int width, int height)
{
// 对每个像素执行误差扩散
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
int index = y * width + x;
unsigned char oldPixel = image[index];
unsigned char newPixel = (oldPixel < 128) ? 0 : 255; // 二值化
// 计算误差
int error = oldPixel - newPixel;
// 更新当前像素
image[index] = newPixel;
// 误差扩散到相邻像素
if(x < width - 1) {
image[index + 1] = restrain_int(image[index + 1] + (error * 7 / 16));
}
if(y < height - 1) {
image[index + width] = restrain_int(image[index + width] + (error * 5 / 16));
}
if(x < width - 1 && y < height - 1) {
image[index + width + 1] = restrain_int(image[index + width + 1] + (error * 1 / 16));
}
if(x > 0 && y < height - 1) {
image[index + width - 1] = restrain_int(image[index + width - 1] + (error * 3 / 16));
}
}
}
}
static void printer_work_task()
{
uint32_t itk = 0;
uint32_t ktk = 0;
uint32_t jtk = 0;
int32_t tm;
uint32_t grep_step = 0;
halfstep_buf = (uint8_t*)os_malloc((TEST_MOTO_BUF_COUNT*4+1));
if(halfstep_buf == NULL)
{
os_printf("malloc halfstep_buf fail, printer thread end\r\n");
goto __exit;
}
halfstep_buf_cache = (uint8_t*)os_malloc((TEST_MOTO_BUF_COUNT*4+1));
if(halfstep_buf_cache == NULL)
{
os_printf("malloc halfstep_buf_cache fail, printer thread end\r\n");
os_free(halfstep_buf);
halfstep_buf = NULL;
goto __exit;
}
printer_buf = (uint8_t*)os_malloc_psram(PRINTER_W * PRINTER_H);
if(printer_buf == NULL)
{
os_printf("malloc printer_buf fail, printer thread end\r\n");
os_free_psram(printer_buf);
printer_buf = NULL;
goto __exit;
}
printer_buf_odd = (uint8_t*)os_malloc(HEAT_BYTES_PER_LINE);
if(printer_buf_odd == NULL)
{
os_printf("malloc printer_buf_odd fail, printer thread end\r\n");
os_free(printer_buf_odd);
printer_buf_odd = NULL;
goto __exit;
}
printer_buf_even = (uint8_t*)os_malloc(HEAT_BYTES_PER_LINE);
if(printer_buf_even == NULL)
{
os_printf("malloc printer_buf_even fail, printer thread end\r\n");
os_free(printer_buf_even);
printer_buf_even = NULL;
goto __exit;
}
while(1){
//开始打印前建议先关闭比spi优先级更高的中断(LCD、USB、UART),避免其他中断占用时间长影响打印效果
if (printer_action == 0 || printer_done == 0) {
//printf("-->Printer0 wait!\r\n");
os_sleep_ms(50);
continue;
}
printer_action = 0;
printer_done = 0;
pre_heat_flag = 0;
printer_h = PRINTER_H;
os_printf("-->Printer0 open!\r\n");
paper_io_init(); //打印机IO初始化
//gpio_set_val(PRINTER_EN_PIN,1); //enable printer power
printer_dvp_en_exchange(1);
printer_delay(500);
os_printf("-->Printer0 open finish!\r\n");
if(is_paper_insert()) // check paper
{
//gpio_set_val(PRINTER_EN_PIN,0); //disable printer power
paper_io_deinit();
printer_dvp_en_exchange(0);
os_printf("-->Printer error...no paper!!!\r\n");
continue;
}
os_printf("%s %d\n",__FUNCTION__,__LINE__);
tm = get_printer_tm(); //check tm
if(1 == tm) // hot
{
//gpio_set_val(PRINTER_EN_PIN,0); //disable printer power
paper_io_deinit();
printer_dvp_en_exchange(0);
os_printf("-->Get the TM error...\r\n");
continue;
}
os_printf("%s %d\n",__FUNCTION__,__LINE__);
os_memset(printer_buf, 0, PRINTER_W * PRINTER_H); //384 x 512
#if PRINTER_DITHERING_EN
dithering(vga_room, PRINTER_W, PRINTER_H); //半色调散点特效
#endif
#if PRINTER_TEST_PATTER_EN
printer_set_picture_addr(printer_demo); //打印图片
#else
printer_set_picture_addr(vga_room);
#endif
for(itk = 0; itk < PRINTER_H; itk++) { //384 x 512
for(ktk = 0; ktk < PRINTER_W; ktk++) {
grep_step = 0;
for(jtk = 0; jtk < 64; jtk++) { //配置打印图片量化系数
if(printer_picture_addr[itk*PRINTER_W+ktk] < (grep_step*4)/*255*/) { //64 4
printer_buf[itk*PRINTER_W+(PRINTER_W-1)-ktk]++;
}
grep_step++;
}
}
}
enhanceContrast(printer_buf);
os_printf("%s %d\n",__FUNCTION__,__LINE__);
os_memset(printer_buf_even, 0, HEAT_BYTES_PER_LINE);
os_memset(printer_buf_odd, 0, HEAT_BYTES_PER_LINE);
for(jtk = 0; jtk < HEAT_BYTES_PER_LINE; jtk++)
{
for(itk = 1; itk < 8; itk+=2)
{
if ((printer_buf[jtk*8+itk]) > 0 && (1)) {
printer_buf[jtk*8+itk]--;
printer_buf_odd[jtk] |= (1 << (7-itk));
}
}
}
os_printf("%s %d\n",__FUNCTION__,__LINE__);
os_memset(printer_buf_even, 0xFF, HEAT_BYTES_PER_LINE);
spi_ioctl((struct spi_device*)spi0_dev, SPI_KICK_DMA_TX, (uint32)printer_buf_even, HEAT_BYTES_PER_LINE);
while(!spi_ioctl((struct spi_device*)spi0_dev, SPI_GET_DMA_PENDING, 0, 0))
{
os_sleep_ms(1);
};
spi_ioctl((struct spi_device*)spi0_dev, SPI_CLEAR_DMA_PENDING, 1, 0);
os_memset(printer_buf_even, 0, HEAT_BYTES_PER_LINE);
gpio_set_val(PRINTER_LATCH_PIN,0);
gpio_set_val(PRINTER_LATCH_PIN,1);
//加热部分使用timer控制时间取消关中断操作
struct timer_device *stb_timer0 = (struct timer_device *)printer_stb_timer_open();
printer_stb_start((void*)stb_timer0, 30); //预加热 30ms
while (pre_heat_flag == 0) {
os_sleep_ms(10);
}
printer_moto_enable(1);
spi_request_irq(spi0_dev, SPI_IRQ_FLAG_TX_DONE, spi0_irq, (uint32)halfstep_buf);
last_ret = 1;
//触发中断打印状态机
spi_ioctl((struct spi_device*)spi0_dev, SPI_KICK_DMA_TX, (uint32)printer_buf_even, HEAT_BYTES_PER_LINE);
//等待打印结束
while (printer_done != 1)
{
os_sleep_ms(100);
}
gpio_set_val(PRINTER_EN_PIN,0); //disable printer power
printer_stb_timer_close((void*)stb_timer0);
paper_io_deinit();
printer_dvp_en_exchange(0);
os_printf("printer stop....\r\n");
}
//理论上没有处理循环退出操作此处buff未释放
__exit:
if (halfstep_buf) {
os_free(halfstep_buf);
halfstep_buf = NULL;
}
if (halfstep_buf_cache) {
os_free(halfstep_buf_cache);
halfstep_buf_cache = NULL;
}
if (printer_buf) {
os_free_psram(printer_buf);
printer_buf = NULL;
}
if (printer_buf_odd) {
os_free(printer_buf_odd);
printer_buf_odd = NULL;
}
if (printer_buf_even) {
os_free(printer_buf_even);
printer_buf_even = NULL;
}
}
int32 atcmd_printer_action(const char *cmd, char *argv[], uint32 argc)
{
if(os_atoi(argv[0])) {
printer_kick_start();
}
return 0;
}
void printer_thread_init()
{
os_task_create("printer", printer_work_task, NULL, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
}
#endif