分类 学习笔记 下的文章

微雪4.2寸WiFi电子墨水屏GO版示例

360px-4.2inch_e-Paper_Cloud_Module_wiki.jpg

这块板子自带了充电电池、WiFi蓝牙模块、充电模块。

package main

import (
    "bytes"
    "encoding/binary"
    "errors"
    "fmt"
    "net"
    "strconv"

    "github.com/Comdex/imgo"
)

var (
    g_width       = 400
    g_hight       = 300
    g_frame_len   = 1024 //每次传输数据长度不应超过1100Byte,否则将会导致数据丢失.???
    g_sector_size = 4096 //扇区大小
)

func check_res(res []byte) (cr []byte, err error) {
    if res[0] != '$' {
        return cr, errors.New("接收头错误")
    }
    i := bytes.LastIndexByte(res, '#')
    if i == -1 {
        return cr, errors.New("接收尾错误")
    }
    return res[1:i], err
}

func send_cmd(conn net.Conn, cmd []byte, hr bool) (res []byte, err error) {
    var check byte
    for _, b := range cmd {
        check ^= b
    }
    buf := new(bytes.Buffer)
    binary.Write(buf, binary.BigEndian, ';')
    binary.Write(buf, binary.BigEndian, cmd)
    binary.Write(buf, binary.BigEndian, '/')
    binary.Write(buf, binary.BigEndian, check)
    conn.Write(buf.Bytes())

    rdata := make([]byte, 64)
    rl, _ := conn.Read(rdata)
    rd, err := check_res(rdata[:rl])
    if err != nil {
        return res, err
    }
    if len(rd) != 1 || rd[0] != check {
        return res, errors.New("发送数据错误")
    }
    if hr == false {
        return
    }
    rl, _ = conn.Read(rdata)
    return check_res(rdata[:rl])
}

func send_data(conn net.Conn, data []byte) error {
    var check byte
    for _, b := range data {
        check ^= b
    }
    buf := new(bytes.Buffer)
    err := binary.Write(buf, binary.BigEndian, uint8(0x57))
    binary.Write(buf, binary.BigEndian, data)
    binary.Write(buf, binary.BigEndian, check)
    conn.Write(buf.Bytes())

    rdata := make([]byte, 64)
    rl, _ := conn.Read(rdata)
    rd, err := check_res(rdata[:rl])
    if err != nil {
        return nil
    }
    if len(rd) != 1 || rd[0] != check {
        return errors.New("发送数据错误")
    }
    return nil
}

func flush_buffer(conn net.Conn, img []byte) {
    res, err := send_cmd(conn, []byte("F"), false)
    fmt.Println("刷写数据", string(res), err)

    for i := 0; i < len(img)/g_frame_len; i++ {
        addr := i * g_frame_len
        num := addr % g_sector_size / g_frame_len //扇区的第几块? num因版本升级而失去作用,可为恒定值???
        data := new(bytes.Buffer)
        binary.Write(data, binary.BigEndian, uint32(addr))
        binary.Write(data, binary.BigEndian, uint32(g_frame_len))
        binary.Write(data, binary.BigEndian, uint8(num))
        binary.Write(data, binary.BigEndian, img[addr:addr+g_frame_len])
        send_data(conn, data.Bytes())
    }
    if len(img)%g_frame_len != 0 {
        addr := len(img) / g_frame_len * g_frame_len
        num := addr % g_sector_size / g_frame_len //扇区的第几块? num因版本升级而失去作用,可为恒定值???
        data := new(bytes.Buffer)
        binary.Write(data, binary.BigEndian, uint32(addr))
        binary.Write(data, binary.BigEndian, uint32(len(img)-addr))
        binary.Write(data, binary.BigEndian, uint8(num))
        binary.Write(data, binary.BigEndian, img[addr:])
        send_data(conn, data.Bytes())
    }
    data := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} //当addr和len均为0时,退出刷新模式。并自动刷新屏幕。???
    send_data(conn, data)

    res, err = send_cmd(conn, []byte("D"), false)
    fmt.Println("显示数据", string(res), err)
}

func img_to_400_300_bin(p string) (bw []byte, err error) {
    img43, err := imgo.ResizeForMatrix(p, g_width, g_hight) //调整大小
    if err != nil {
        return
    }
    //imgo.SaveAsJPEG("clo.jpg", img43, 100)

    imgb := imgo.Binaryzation(img43, 127) //黑白化
    //imgo.SaveAsJPEG("bin.jpg", imgb, 100)

    bw = make([]byte, g_width/8*g_hight) //生成画布 一比特一像素

    for i := 0; i < len(imgb); i++ { //高
        for j := 0; j < len(imgb[0]); j++ { //宽
            var r uint8
            if imgb[i][j][0] == 0 { //rgba
                r = 0
            } else {
                r = 1
            }
            pos := i*len(imgb[0]) + j
            bw[pos/8] |= r << (8 - (pos % 8) - 1) //按位填充数据
        }
    }
    return
}

func doServerStuff(conn net.Conn) {
    defer conn.Close()

    res, err := send_cmd(conn, []byte("G"), true)
    fmt.Println("主机名", string(res), err)

    res, err = send_cmd(conn, []byte("C"), true)
    fmt.Println("是否有锁", string(res), err)

    res, err = send_cmd(conn, []byte("N123456"), true)
    fmt.Println("解锁结果", string(res), err)

    res, err = send_cmd(conn, []byte("b"), true)
    b, _ := strconv.Atoi(string(res))
    fmt.Println("电池电压", b*3, err)

    bw, _ := img_to_400_300_bin(`C:\123.jpg`)
    flush_buffer(conn, bw)

    for {
        res, err = send_cmd(conn, []byte("b"), true)
        b, _ := strconv.Atoi(string(res))
        fmt.Println("电池电压", b*3, err)
    }
}

func main() {
    fmt.Println("开启服务")
    listener, err := net.Listen("tcp", ":6868")
    if err != nil {
        fmt.Println("监听失败", err)
        return
    }
    defer listener.Close()
    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("接收新客户失败", err)
            return
        }
        fmt.Println("接收到新客户", conn.RemoteAddr())
        go doServerStuff(conn)
    }
}

自己翻译成go语言版,非常粗糙能跑通版。
官方文档地址 https://www.waveshare.net/wiki/4.2inch_e-Paper_Cloud_Module

QT上C++和OC混编的一些记录

QT的pro配置文件里加上

#开启ARC,QT上C++和OC混编默认是没有开启ARC的。
QMAKE_OBJECTIVE_CFLAGS += -fobjc-arc

OBJECTIVE_HEADERS += \
    aaa.h \
    bbb.h

OBJECTIVE_SOURCES += \
    aaa.mm \
    bbb.m

#框架
LIBS += -framework Foundation
LIBS += -framework Cocoa

C/C++和OC混编代码要写到.mm文件里,.cpp文件要引用到的.h头文件里不能包含有OC的代码或头文件,所以一般都要封装一下导出为C/C++的头文件。

网上找的一些资料
https://awhisper.github.io/2016/05/01/%E6%B7%B7%E7%BC%96ObjectiveC/
http://zsaber.com/blog/p/147
https://blog.csdn.net/horkychen/article/details/7935910

学习OC的好文章
http://www.runoob.com/w3cnote/objective-c-tutorial.html