~aleteoryx/muditaos

ref: 3cbbeff551230786ae13c23a7bf4fa8c50099896 muditaos/module-bsp/board/linux/eink/ED028TC1.c -rw-r--r-- 5.1 KiB
3cbbeff5 — Lefucjusz [MOS-1011] Fix frequency switching stability 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/**
 * @brief EInk ED028TC1 electronic paper display driver
 * @details This is hardware specific electronic paper display ED028TC1 driver.
 *
 * @note All the commands implemented in here are based on the datasheets:
 *              * ED028TC1 Product Preliminary Spec sheet v0.4 20171228.pdf
 *              * UC8177c.pdf
 */

#include "ED028TC1.h"
#include "board.h"

#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <string.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#include "macros.h"

// header of the eink's shared memory frame buffer.
typedef struct
{
    uint32_t frameCount;
    uint32_t width;
    uint32_t height;
} shared_memory_header;
// pointer to the header in the shared memory
static shared_memory_header *shared_header = NULL;
// pointe to the buffer ( located in memory right after shared header )
static uint8_t *shared_buffer = NULL;
// pointer to the buffer that simulates internal einks buffer. Image from the eink service is copied to first to this
// buffer durinig update operation. When refresh is called image from this buffer is copied to the shared memory.
static uint8_t *eink_internal_buffer = NULL;
// size of the buffer in bytes
static int shared_buffer_size = BOARD_EINK_DISPLAY_RES_X * BOARD_EINK_DISPLAY_RES_Y;

int shared_fd = 0;

static uint8_t s_einkIsPoweredOn = false; //  Variable which contains the state of the power of the EPD display

uint8_t EinkIsPoweredOn()
{
    return s_einkIsPoweredOn;
}

void EinkPowerOn()
{
    s_einkIsPoweredOn = true;
}

void EinkPowerOff()
{
    s_einkIsPoweredOn = false;
}

void EinkPowerDown(void)
{
    EinkPowerOff();
}

static shared_memory_header *createSHMBuffer(const char *name)
{
    if (shared_header != NULL)
        return shared_header;

    // check if shared memory blok is already created
    if ((shared_fd = shm_open(name, O_RDWR | O_CREAT, 0660)) == -1) {
        printf("shm is already created");
    }
    else {
        if (ftruncate(shared_fd, sizeof(shared_memory_header) + shared_buffer_size) == -1) {
            printf("shm is already created");
        }
    }
    if ((shared_header = mmap(NULL,
                              sizeof(shared_memory_header) + shared_buffer_size,
                              PROT_READ | PROT_WRITE,
                              MAP_SHARED,
                              shared_fd,
                              0)) == MAP_FAILED) {
        printf("mmap failed");
    }

    shared_buffer        = ((uint8_t *)shared_header) + sizeof(shared_memory_header);
    eink_internal_buffer = shared_buffer + shared_buffer_size;

    return shared_header;
}

// on linux this function is responsible for creating/opeingin shared memory region where image from eink task will be
// copied
EinkStatus_e EinkResetAndInitialize()
{

    s_einkIsPoweredOn = false;

    // create and map shared memory
    char *shared_name = "pure_gui_fmbuf";
    if (createSHMBuffer(shared_name) == NULL) {
        return EinkError;
    }

    // start renderer application
    if (system("LD_PRELOAD=;./service_renderer &") < 0) {
        perror("system");
        return EinkError;
    }
    return EinkOK;
}

EinkStatus_e EinkUpdateFrame(EinkFrame_t frame, const uint8_t *buffer)
{
    uint32_t offset_eink   = frame.pos_y * BOARD_EINK_DISPLAY_RES_X + frame.pos_x;
    uint32_t offset_buffer = 0;
    for (uint32_t h = 0; h < frame.height; ++h) {
        memcpy(shared_buffer + offset_eink, buffer + offset_buffer, frame.width);
        offset_eink += BOARD_EINK_DISPLAY_RES_X;
        offset_buffer += frame.width;
    }

    shared_header->frameCount++;
    return EinkOK;
}

EinkStatus_e EinkFillScreenWithColor(EinkDisplayColorFilling_e colorFill)
{
    if (shared_buffer && shared_header) {
        memset(shared_buffer, colorFill, shared_buffer_size);
        return EinkOK;
    }

    return EinkError;
}

EinkStatus_e EinkRefreshImage(EinkFrame_t frame)
{
    return EinkOK;
}

__attribute__((optimize("O3"))) void EinkARGBToLuminance(uint8_t *dataIn,
                                                         uint8_t *dataOut,
                                                         uint32_t displayWidth,
                                                         uint32_t displayHeight)
{
    uint8_t r, g, b;
    float fi;
    uint32_t *src;
    uint8_t *dst;

    src = (uint32_t *)dataIn;
    dst = (uint8_t *)dataOut;

    for (uint32_t i = 0; i < (displayWidth * displayHeight);
         i += 2) // increase by 8 pixels - 32bit word is 8 pixels in 4BPP
    {
        *dst = 0x00000000;
        for (uint8_t j = 0; j < 8; j += 4) {
            r  = (uint8_t)((*(src)) >> 16);
            g  = (uint8_t)((*(src)) >> 8);
            b  = (uint8_t) * (src);
            fi = (r + g + b) / 3;

            *dst |= ((uint32_t)(floor(fi / 16))) << (4 - j);

            src++;
        }
        dst++;
    }
}

EinkStatus_e EinkMemcpyDmaInit(edma_callback memcpyCallback)
{
    return EinkOK;
}