|
|
|
@ -2,7 +2,7 @@
|
|
|
|
|
libS2245ImageReProcess -- Re-implemented Image Processing library for
|
|
|
|
|
the Sinfonia CHC-S2245 printer family
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2021 Solomon Peachy <pizza@shaftnet.org>
|
|
|
|
|
Copyright (c) 2021-2024 Solomon Peachy <pizza@shaftnet.org>
|
|
|
|
|
|
|
|
|
|
** ** ** ** Do NOT contact Sinfonia about this library! ** ** ** **
|
|
|
|
|
|
|
|
|
@ -39,7 +39,7 @@
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define LIB_VERSION "0.1.2"
|
|
|
|
|
#define LIB_VERSION "0.1.3"
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
@ -83,6 +83,8 @@ bool ip_getMemorySize(uint32_t *szMemory,
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
// External data formats
|
|
|
|
|
|
|
|
|
|
#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed")
|
|
|
|
|
|
|
|
|
|
struct ippHeatCorr {
|
|
|
|
|
int32_t tankDivisor[4];
|
|
|
|
|
int32_t tankRowInitVals[4];
|
|
|
|
@ -118,6 +120,8 @@ struct SIppData {
|
|
|
|
|
uint8_t sideEdgeCorrectionTable[256];
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(struct SIppData) == 2524);
|
|
|
|
|
|
|
|
|
|
struct ippHeader {
|
|
|
|
|
char model[16];
|
|
|
|
|
char ipp[4];
|
|
|
|
@ -125,6 +129,8 @@ struct ippHeader {
|
|
|
|
|
uint8_t pad_0x15[43];
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(struct ippHeader) == 64);
|
|
|
|
|
|
|
|
|
|
struct ippConf {
|
|
|
|
|
uint16_t width; /* Overridden at runtime */
|
|
|
|
|
uint16_t height; /* Overridden at runtime */
|
|
|
|
@ -136,19 +142,58 @@ struct ippConf {
|
|
|
|
|
uint8_t borderCapable; // 0x02 if we can do 5x7-on-6x8
|
|
|
|
|
uint8_t pad_0xb[21];
|
|
|
|
|
uint8_t planeOrder[16];
|
|
|
|
|
uint8_t pad_0x30[16];
|
|
|
|
|
uint8_t pad_0x20[16];
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(struct ippConf) == 64);
|
|
|
|
|
|
|
|
|
|
struct ippData {
|
|
|
|
|
struct ippHeader header;
|
|
|
|
|
struct ippConf conf;
|
|
|
|
|
struct SIppData plane_rc;
|
|
|
|
|
/*@00*/ struct ippHeader header;
|
|
|
|
|
/*@40*/ struct ippConf conf;
|
|
|
|
|
/*@80*/ struct SIppData plane_rc;
|
|
|
|
|
struct SIppData plane_gm;
|
|
|
|
|
struct SIppData plane_by;
|
|
|
|
|
struct SIppData plane_oc;
|
|
|
|
|
// Can have up to 16 planes, think about this.
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(struct ippData) == 10224);
|
|
|
|
|
|
|
|
|
|
struct ippConfKA {
|
|
|
|
|
uint16_t width; /* Overridden at runtime */
|
|
|
|
|
uint16_t height; /* Overridden at runtime */
|
|
|
|
|
uint16_t headWidth; // Always 1920
|
|
|
|
|
uint8_t planes; // 3 or 4, can be up to 16!
|
|
|
|
|
uint8_t printmode; // Corresponds to corrdata_req field 1
|
|
|
|
|
uint8_t corrections1; // Corresponds to corrdata_req field 2
|
|
|
|
|
uint8_t corrections2; // B0,B1,B2
|
|
|
|
|
uint8_t borderCapable; // 0x02 if we can do 5x7-on-6x8
|
|
|
|
|
uint8_t pad_0xb[21];
|
|
|
|
|
uint8_t planeOrder[16];
|
|
|
|
|
uint8_t num_panels; /* 0x01-0x03 ? */
|
|
|
|
|
uint8_t unk_0x21; /* 0x06 in IPP, 0x00 or 0x01 in cmd */
|
|
|
|
|
uint16_t unk_0x22; /* 0x0032 */
|
|
|
|
|
uint16_t max_panel_overlap; /* 0x0258 == 600d */
|
|
|
|
|
uint16_t panel_rows[3]; /* */
|
|
|
|
|
uint16_t lam_rows[3]; /* */
|
|
|
|
|
uint16_t unk_0x42[31];
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(struct ippConfKA) == 128); /* KA6900 */
|
|
|
|
|
|
|
|
|
|
struct ippDataKA {
|
|
|
|
|
/*@00*/ struct ippHeader header;
|
|
|
|
|
/*@40*/ struct ippConfKA conf;
|
|
|
|
|
/*@c0*/ struct SIppData plane_rc;
|
|
|
|
|
struct SIppData plane_gm;
|
|
|
|
|
struct SIppData plane_by;
|
|
|
|
|
struct SIppData plane_oc;
|
|
|
|
|
uint8_t pad[7680]; /* @ 10288 */
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(struct ippDataKA) == 17968);
|
|
|
|
|
|
|
|
|
|
#undef STATIC_ASSERT
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
// Private Structures
|
|
|
|
|
|
|
|
|
@ -173,14 +218,15 @@ struct CHeatCorrProc {
|
|
|
|
|
|
|
|
|
|
struct CIppMng {
|
|
|
|
|
struct ippHeader header;
|
|
|
|
|
struct ippConf conf;
|
|
|
|
|
struct ippConfKA conf;
|
|
|
|
|
struct SIppData *ippData;
|
|
|
|
|
uint8_t initialized;
|
|
|
|
|
uint8_t ka6900;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct CImageProc {
|
|
|
|
|
struct CIppMng *ippMng;
|
|
|
|
|
struct ippConf conf;
|
|
|
|
|
struct ippConfKA conf;
|
|
|
|
|
struct SIppData planeIPPdata;
|
|
|
|
|
uint32_t pixelsOCG; // width*height*3
|
|
|
|
|
uint32_t pixelsOCM; // width*height*4
|
|
|
|
@ -228,13 +274,6 @@ struct pic_data {
|
|
|
|
|
uint8_t bytes_pp;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Data format Sanity checks
|
|
|
|
|
#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed")
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(struct ippData) == 10224);
|
|
|
|
|
|
|
|
|
|
#undef STATIC_ASSERT
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
// Private data declarations
|
|
|
|
|
|
|
|
|
@ -257,30 +296,47 @@ static void CIppMng_Cleanup(struct CIppMng *this)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char s2245HeaderModel[] = "CHC-S2245 ";
|
|
|
|
|
static const char s2245IppStr[] = "IPP=";
|
|
|
|
|
static const char ka6900HeaderModel[] = "KA6900 ";
|
|
|
|
|
static const char ippStr[] = "IPP=";
|
|
|
|
|
|
|
|
|
|
static bool CIppMng_CheckHeader(struct CIppMng *this, struct ippData *ippData)
|
|
|
|
|
static bool CIppMng_CheckHeader(struct CIppMng *this, void *ippData)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
memcpy(&this->header, &ippData->header, sizeof(this->header));
|
|
|
|
|
memcpy(&this->header, ippData, sizeof(this->header));
|
|
|
|
|
|
|
|
|
|
if (memcmp(this->header.model, s2245HeaderModel, 16))
|
|
|
|
|
return 0;
|
|
|
|
|
if (memcmp(this->header.ipp, s2245IppStr, 4))
|
|
|
|
|
return 0;
|
|
|
|
|
if (this->header.version != 0x3)
|
|
|
|
|
if (this->ka6900) {
|
|
|
|
|
if (memcmp(this->header.model, ka6900HeaderModel, 16))
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
if (memcmp(this->header.model, s2245HeaderModel, 16))
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (memcmp(this->header.ipp, ippStr, 4))
|
|
|
|
|
return 0;
|
|
|
|
|
if (this->ka6900) {
|
|
|
|
|
if (this->header.version != 0x7)
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
if (this->header.version != 0x3)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CIppMng_CheckConf(struct CIppMng *this, struct ippData *ippData)
|
|
|
|
|
static bool CIppMng_CheckConf(struct CIppMng *this, void *ippData)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
uint8_t tmp;
|
|
|
|
|
|
|
|
|
|
#ifndef USE_EXTRA_STUFF
|
|
|
|
|
memcpy(&this->conf, &ippData->conf, sizeof(this->conf));
|
|
|
|
|
if (this->ka6900) {
|
|
|
|
|
struct ippDataKA *data = ippData;
|
|
|
|
|
memcpy(&this->conf, &data->conf, sizeof(this->conf));
|
|
|
|
|
} else {
|
|
|
|
|
struct ippData *data = ippData;
|
|
|
|
|
memcpy(&this->conf, &data->conf, sizeof(this->conf));
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
(void)ippData;
|
|
|
|
|
#endif
|
|
|
|
@ -298,40 +354,62 @@ static bool CIppMng_CheckConf(struct CIppMng *this, struct ippData *ippData)
|
|
|
|
|
if (tmp > 1)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
// XXX anything else for KA6900?
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CIppMng_CheckIpp(struct CIppMng *this, struct ippData *ippData)
|
|
|
|
|
static bool CIppMng_CheckIpp(struct CIppMng *this, void *ippData)
|
|
|
|
|
{
|
|
|
|
|
bool rval;
|
|
|
|
|
|
|
|
|
|
rval = CIppMng_CheckHeader(this, ippData);
|
|
|
|
|
|
|
|
|
|
if (rval)
|
|
|
|
|
rval = CIppMng_CheckConf(this, ippData);
|
|
|
|
|
|
|
|
|
|
return rval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CIppMng_SetConf(struct CIppMng *this, struct ippData *ippData,
|
|
|
|
|
static bool CIppMng_SetConf(struct CIppMng *this, void *ippData,
|
|
|
|
|
uint16_t width, uint16_t height)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
memcpy(&this->conf, &ippData->conf, sizeof(this->conf));
|
|
|
|
|
if (!memcmp(ippData, ka6900HeaderModel, sizeof(ka6900HeaderModel)-1))
|
|
|
|
|
this->ka6900 = 1;
|
|
|
|
|
|
|
|
|
|
if (!width || !height)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (this->ka6900) {
|
|
|
|
|
struct ippDataKA *data = ippData;
|
|
|
|
|
memcpy(&this->conf, &data->conf, sizeof(this->conf));
|
|
|
|
|
} else {
|
|
|
|
|
struct ippData *data = ippData;
|
|
|
|
|
memcpy(&this->conf, &data->conf, sizeof(this->conf));
|
|
|
|
|
memset(&this->conf + sizeof(data->conf), 0, sizeof(this->conf) - sizeof(data->conf));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->conf.width = width;
|
|
|
|
|
this->conf.height = height;
|
|
|
|
|
|
|
|
|
|
#if (__BYTE_ORDER != __LITTLE_ENDIAN)
|
|
|
|
|
this->conf.headWidth = le16_to_cpu(this->conf.headWidth);
|
|
|
|
|
#endif
|
|
|
|
|
if (this->ka6900) {
|
|
|
|
|
this->conf.max_panel_overlap = le16_to_cpu(this->conf.max_panel_overlap);
|
|
|
|
|
this->conf.unk_0x22 = le16_to_cpu(this->conf.unk_0x22); // XXX
|
|
|
|
|
for (int i = 0 ; i < 3 ; i++) {
|
|
|
|
|
this->conf.panel_rows[i] = le16_to_cpu(this->conf.panel_rows[i]);
|
|
|
|
|
this->conf.lam_rows[i] = le16_to_cpu(this->conf.lam_rows[i]);
|
|
|
|
|
}
|
|
|
|
|
// XXX additional fields.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CIppMng_SetData(struct CIppMng *this, struct ippData *ippData)
|
|
|
|
|
static bool CIppMng_SetData(struct CIppMng *this, void *ippData)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
if (this->ippData)
|
|
|
|
@ -344,19 +422,26 @@ static bool CIppMng_SetData(struct CIppMng *this, struct ippData *ippData)
|
|
|
|
|
if (!this->ippData)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
memcpy(this->ippData, &ippData->plane_rc, this->conf.planes * sizeof(*this->ippData));
|
|
|
|
|
if (this->ka6900) {
|
|
|
|
|
struct ippDataKA *data = ippData;
|
|
|
|
|
memcpy(this->ippData, &data->plane_rc, this->conf.planes * sizeof(*this->ippData));
|
|
|
|
|
} else {
|
|
|
|
|
struct ippData *data = ippData;
|
|
|
|
|
memcpy(this->ippData, &data->plane_rc, this->conf.planes * sizeof(*this->ippData));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if (__BYTE_ORDER != __LITTLE_ENDIAN)
|
|
|
|
|
#define SWAP16(__x) __x = le16_to_cpu(ippBlock->__x)
|
|
|
|
|
#define SWAP32(__x) __x = le32_to_cpu(ippBlock->__x)
|
|
|
|
|
#define swap16(__x) ippBlock->__x = le16_to_cpu(ippBlock->__x)
|
|
|
|
|
#define swap32(__x) ippBlock->__x = le32_to_cpu(ippBlock->__x)
|
|
|
|
|
|
|
|
|
|
int i, j;
|
|
|
|
|
for (i = 0 ; i < this->conf.planes ; i++) {
|
|
|
|
|
struct SIppData *ippBlock = &ippData->plane_rc + i;
|
|
|
|
|
struct SIppData *ippBlock = &this->ippData[i];
|
|
|
|
|
swap16(field_0x0);
|
|
|
|
|
swap16(field_0x2);
|
|
|
|
|
swap16(maxLineSum);
|
|
|
|
|
swap16(minRowSum);
|
|
|
|
|
swap16(maxLineCorrecitonFactor);
|
|
|
|
|
swap16(maxLineCorrectionFactor);
|
|
|
|
|
swap16(nextWeight);
|
|
|
|
|
swap16(prevWeight);
|
|
|
|
|
swap16(mtfPreCalcCutoff);
|
|
|
|
@ -365,7 +450,7 @@ static bool CIppMng_SetData(struct CIppMng *this, struct ippData *ippData)
|
|
|
|
|
swap16(pulseExMap[j]);
|
|
|
|
|
swap16(heatCorrectionMinusTable[j]);
|
|
|
|
|
swap16(heatCorrectionPlusTable[j]);
|
|
|
|
|
swap16(lineCorrection);
|
|
|
|
|
swap16(lineCorrection[j]);
|
|
|
|
|
}
|
|
|
|
|
for (j = 0 ; j < 4 ; j++) {
|
|
|
|
|
swap32(heatCorrection.tankDivisor[j]);
|
|
|
|
@ -375,20 +460,20 @@ static bool CIppMng_SetData(struct CIppMng *this, struct ippData *ippData)
|
|
|
|
|
for (j = 0 ; j < 5 ; j++) {
|
|
|
|
|
swap32(heatCorrection.tankCoef[j]);
|
|
|
|
|
}
|
|
|
|
|
swap32(tankPlusParam);
|
|
|
|
|
swap32(tankMinusParam);
|
|
|
|
|
swap32(tankPlusLimit);
|
|
|
|
|
swap32(tankMinusLimit);
|
|
|
|
|
swap32(useHeatCorrection);
|
|
|
|
|
swap32(heatCorrection.tankPlusParam);
|
|
|
|
|
swap32(heatCorrection.tankMinusParam);
|
|
|
|
|
swap32(heatCorrection.tankPlusLimit);
|
|
|
|
|
swap32(heatCorrection.tankMinusLimit);
|
|
|
|
|
swap32(heatCorrection.useHeatCorrection);
|
|
|
|
|
}
|
|
|
|
|
#undef SWAP16
|
|
|
|
|
#undef SWAP32
|
|
|
|
|
#undef swap16
|
|
|
|
|
#undef swap32
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CIppMng_SetIPP(struct CIppMng *this, struct ippData *ippData,
|
|
|
|
|
static bool CIppMng_SetIPP(struct CIppMng *this, void *ippData,
|
|
|
|
|
uint16_t width, uint16_t height)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
@ -418,7 +503,7 @@ static bool CIppMng_GetNumOfColor(struct CIppMng *this, uint8_t *planesOCG, uint
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CIppMng_GetIppConf(struct CIppMng *this, struct ippConf *conf,
|
|
|
|
|
static bool CIppMng_GetIppConf(struct CIppMng *this, struct ippConfKA *conf,
|
|
|
|
|
uint8_t *planesOCG, uint8_t *planesOCM)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
@ -1707,22 +1792,36 @@ bool ip_getMemorySize(uint32_t *szMemory,
|
|
|
|
|
uint16_t width, uint16_t height,
|
|
|
|
|
void *srcIpp)
|
|
|
|
|
{
|
|
|
|
|
struct ippData *ippData;
|
|
|
|
|
struct CIppMng ippMng;
|
|
|
|
|
uint32_t pixels;
|
|
|
|
|
|
|
|
|
|
if (!width || !height || !szMemory || !srcIpp)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
ippData = srcIpp;
|
|
|
|
|
CIppMng_Init(&ippMng);
|
|
|
|
|
|
|
|
|
|
if ((ippData->conf.borderCapable == 0x02) &&
|
|
|
|
|
#ifdef USE_EXTRA_STUFF
|
|
|
|
|
int rval = CIppMng_SetConf(&ippMng, srcIpp, width, height);
|
|
|
|
|
#else
|
|
|
|
|
int rval = CIppMng_CheckIpp(&ippMng, srcIpp);
|
|
|
|
|
#endif
|
|
|
|
|
if (!rval) {
|
|
|
|
|
CIppMng_Cleanup(&ippMng);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// XXX KA6900 needs this to be rewritten heavily.
|
|
|
|
|
|
|
|
|
|
if ((ippMng.conf.borderCapable == 0x02) &&
|
|
|
|
|
(width == 1548) && (height == 2140)) {
|
|
|
|
|
pixels = 2434*1844; /* ie 8x6 */
|
|
|
|
|
} else {
|
|
|
|
|
pixels = height * width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*szMemory = pixels * 2 * ippData->conf.planes;
|
|
|
|
|
*szMemory = pixels * 2 * ippMng.conf.planes;
|
|
|
|
|
|
|
|
|
|
CIppMng_Cleanup(&ippMng);
|
|
|
|
|
|
|
|
|
|
if (!*szMemory)
|
|
|
|
|
return 0;
|
|
|
|
|