diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/12x20_horizontal_LSB_1.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/12x20_horizontal_LSB_1.h new file mode 100644 index 00000000..c8f9d8a2 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/12x20_horizontal_LSB_1.h @@ -0,0 +1,98 @@ +const char font[256][40]={ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20 +{0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x21 +{0x00,0x00,0xC0,0x18,0xC0,0x18,0xC0,0x18,0xC0,0x18,0xC0,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x22 +{0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x22,0x00,0x11,0x00,0x11,0x00,0x11,0xE0,0xFF,0x80,0x08,0x80,0x08,0x80,0x08,0xE0,0x7F,0x40,0x04,0x40,0x04,0x20,0x02,0x20,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x23 +{0x00,0x00,0x00,0x04,0x00,0x1F,0x80,0x3F,0xC0,0x24,0xC0,0x04,0xC0,0x04,0x80,0x07,0x00,0x07,0x00,0x1C,0x00,0x1C,0x00,0x34,0x00,0x34,0x40,0x34,0xC0,0x1F,0x80,0x0F,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x24 +{0x00,0x00,0x00,0x00,0xE0,0x81,0x30,0x43,0x30,0x23,0x30,0x13,0x30,0x0B,0x30,0x0B,0xE0,0x05,0x00,0x7A,0x00,0xCD,0x00,0xCD,0x80,0xCC,0x40,0xCC,0x20,0xCC,0x10,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x25 +{0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1F,0x80,0x19,0x80,0x19,0x80,0x0D,0x00,0x07,0xC0,0x03,0x60,0xC6,0x30,0xCE,0x30,0xCC,0x30,0x78,0x70,0x78,0xE0,0x7F,0xC0,0xEF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x26 +{0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x27 +{0x00,0x00,0x00,0x30,0x00,0x3C,0x00,0x0E,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0E,0x00,0x3C,0x00,0x30,0x00,0x00}, // 0x28 +{0x00,0x00,0xC0,0x00,0xC0,0x03,0x00,0x07,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x07,0xC0,0x03,0xC0,0x00,0x00,0x00}, // 0x29 +{0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x60,0x33,0xE0,0x3C,0x00,0x00,0x80,0x0D,0xC0,0x19,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2A +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xE0,0x7F,0xE0,0x7F,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2B +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x00}, // 0x2C +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3F,0xC0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2D +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2E +{0x00,0x00,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x01,0x80,0x01,0x80,0x01,0xC0,0x00,0xC0,0x00,0x60,0x00,0x00,0x00}, // 0x2F +{0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1F,0xC0,0x30,0xC0,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xC0,0x30,0xC0,0x30,0x80,0x1F,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x30 +{0x00,0x00,0x00,0x00,0x00,0x06,0xC0,0x07,0x60,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xE0,0x7F,0xE0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x31 +{0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x1F,0x40,0x38,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x01,0xC0,0x00,0xC0,0x3F,0xC0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x32 +{0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x3F,0x40,0x30,0x00,0x30,0x00,0x18,0x80,0x0F,0x80,0x0F,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x30,0x40,0x38,0xC0,0x1F,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x33 +{0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x1C,0x00,0x1E,0x00,0x1A,0x00,0x19,0x80,0x19,0xC0,0x18,0x40,0x18,0xE0,0x7F,0xE0,0x7F,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x34 +{0x00,0x00,0x00,0x00,0x80,0x3F,0x80,0x3F,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x0F,0x80,0x1F,0x00,0x38,0x00,0x30,0x00,0x30,0x00,0x38,0x80,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x35 +{0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1F,0xC0,0x11,0xC0,0x00,0x60,0x00,0x60,0x0E,0x60,0x1F,0xE0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0xC0,0x38,0xC0,0x1F,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x36 +{0x00,0x00,0x00,0x00,0xC0,0x7F,0xC0,0x7F,0x00,0x60,0x00,0x30,0x00,0x10,0x00,0x18,0x00,0x0C,0x00,0x04,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x03,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x37 +{0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x1F,0xC0,0x18,0xC0,0x18,0xC0,0x19,0x80,0x0F,0x00,0x07,0xC0,0x1E,0x60,0x38,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x38 +{0x00,0x00,0x00,0x00,0x80,0x07,0xC0,0x1F,0xE0,0x18,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x37,0x80,0x33,0x00,0x30,0x00,0x18,0x40,0x1C,0xC0,0x0F,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x39 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3A +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x00}, // 0x3B +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x70,0x00,0x3C,0x00,0x0E,0x80,0x03,0xE0,0x00,0x80,0x03,0x00,0x0E,0x00,0x3C,0x00,0x70,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3C +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x7F,0xE0,0x7F,0x00,0x00,0x00,0x00,0xE0,0x7F,0xE0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3D +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xE0,0x00,0xC0,0x03,0x00,0x07,0x00,0x1C,0x00,0x70,0x00,0x1C,0x00,0x07,0xC0,0x03,0xE0,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3E +{0x00,0x00,0x00,0x00,0xE0,0x0F,0xE0,0x3F,0x20,0x38,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3F +{0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0xC0,0x60,0x60,0x7C,0x30,0x66,0x30,0x63,0x30,0x63,0x30,0x73,0x30,0x73,0x30,0x6F,0x60,0xE6,0x60,0x00,0xC0,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x40 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0F,0x00,0x0F,0x00,0x0D,0x80,0x19,0x80,0x19,0xC0,0x38,0xC0,0x30,0xC0,0x3F,0xE0,0x7F,0x60,0x60,0x60,0x60,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x41 +{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x0F,0xE0,0x1F,0x60,0x18,0x60,0x18,0x60,0x0C,0xE0,0x07,0xE0,0x0F,0x60,0x18,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x1F,0xE0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x42 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0x7F,0xC0,0x41,0xC0,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xC0,0x00,0xC0,0x43,0x80,0x7F,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x43 +{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x0F,0xE0,0x1F,0x60,0x38,0x60,0x70,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x60,0x38,0xE0,0x1F,0xE0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x44 +{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x7F,0xC0,0x7F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x3F,0xC0,0x3F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x7F,0xC0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x45 +{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x7F,0xC0,0x7F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x3F,0xC0,0x3F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x46 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0x7F,0xC0,0x41,0xC0,0x00,0x60,0x00,0x60,0x00,0x60,0x78,0x60,0x78,0x60,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x47 +{0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x3F,0xE0,0x3F,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x48 +{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x1F,0xE0,0x1F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0xE0,0x1F,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x49 +{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x80,0x1F,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x1C,0xC0,0x0F,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4A +{0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x70,0x60,0x38,0x60,0x1C,0x60,0x0E,0x60,0x06,0x60,0x03,0xE0,0x03,0x60,0x07,0x60,0x0E,0x60,0x1C,0x60,0x38,0x60,0x70,0x60,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4B +{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x7F,0xC0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4C +{0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x70,0x70,0xF0,0x78,0xB0,0x68,0xB0,0x68,0xB0,0x6D,0x30,0x65,0x30,0x65,0x30,0x67,0x30,0x62,0x30,0x60,0x30,0x60,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4D +{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x60,0xE0,0x60,0xE0,0x61,0xE0,0x61,0x60,0x63,0x60,0x67,0x60,0x66,0x60,0x6E,0x60,0x6C,0x60,0x78,0x60,0x78,0x60,0x70,0x60,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4E +{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x1F,0xE0,0x38,0x70,0x70,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x70,0x70,0xE0,0x38,0xC0,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4F +{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x1F,0xC0,0x3F,0xC0,0x70,0xC0,0x60,0xC0,0x60,0xC0,0x70,0xC0,0x3F,0xC0,0x0F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x50 +{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x1F,0xE0,0x38,0x70,0x70,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x60,0x30,0xE0,0x38,0xC0,0x1F,0x80,0x0F,0x00,0x38,0x00,0xF0,0x00,0x40,0x00,0x00}, // 0x51 +{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0xE0,0x1F,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x1C,0xE0,0x0F,0xE0,0x07,0x60,0x0E,0x60,0x1C,0x60,0x38,0x60,0x70,0x60,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x52 +{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x1F,0x60,0x10,0x60,0x00,0xE0,0x00,0xC0,0x03,0x80,0x0F,0x00,0x3C,0x00,0x30,0x00,0x30,0x60,0x38,0xE0,0x1F,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x53 +{0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xF0,0xFF,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x54 +{0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x55 +{0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0x60,0x60,0x60,0x60,0xE0,0x60,0xC0,0x30,0xC0,0x30,0xC0,0x31,0x80,0x19,0x80,0x1B,0x00,0x0B,0x00,0x0F,0x00,0x0F,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x56 +{0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xC0,0x30,0xC0,0x30,0xC0,0x20,0x46,0x20,0x46,0x20,0x6E,0x60,0x6F,0x60,0x69,0x60,0x69,0x60,0x39,0xC0,0x39,0xC0,0x39,0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x57 +{0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xE0,0xE0,0x60,0xC0,0x30,0x80,0x19,0x80,0x0F,0x00,0x0F,0x00,0x06,0x00,0x0F,0x80,0x1D,0x80,0x19,0xC0,0x30,0x60,0x70,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x58 +{0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0x60,0x60,0xC0,0x30,0xC0,0x31,0x80,0x19,0x00,0x0F,0x00,0x0F,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x59 +{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x7F,0xE0,0x7F,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x01,0xC0,0x00,0x60,0x00,0xE0,0x7F,0xE0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x5A +{0x00,0x00,0x00,0x3F,0x00,0x3F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x3F,0x00,0x00}, // 0x5B +{0x00,0x00,0x60,0x00,0xC0,0x00,0xC0,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x00}, // 0x5C +{0x00,0x00,0xC0,0x0F,0xC0,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0xC0,0x0F,0xC0,0x0F,0x00,0x00}, // 0x5D +{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x0E,0x00,0x0A,0x00,0x0B,0x00,0x1B,0x80,0x11,0x80,0x31,0xC0,0x30,0xC0,0x20,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x5E +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xF0,0xFF,0x00,0x00,0x00,0x00}, // 0x5F +{0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x60 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0xC0,0x3F,0x40,0x30,0x00,0x30,0x00,0x30,0x80,0x3F,0xC0,0x30,0x60,0x30,0x60,0x38,0xE0,0xFF,0xC0,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x61 +{0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x0E,0x60,0x1F,0xE0,0x39,0xE0,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x18,0xE0,0x1F,0x60,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x62 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xC0,0x3F,0xC0,0x21,0xE0,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xE0,0x00,0xC0,0x01,0xC0,0x3F,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x63 +{0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x80,0x37,0xC0,0x3F,0xC0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x3F,0x80,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x64 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x1F,0xC0,0x38,0x60,0x30,0xE0,0x3F,0xE0,0x3F,0x60,0x00,0x60,0x00,0xC0,0x20,0xC0,0x3F,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x65 +{0x00,0x00,0x00,0x7E,0x00,0x7F,0x00,0x03,0x00,0x03,0xE0,0x7F,0xE0,0x7F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x66 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x37,0xC0,0x3F,0xC0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x3F,0x80,0x37,0x00,0x30,0x40,0x38,0xC0,0x1F,0x80,0x0F}, // 0x67 +{0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x1E,0x60,0x3F,0xE0,0x31,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x68 +{0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0xC0,0x0F,0xC0,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x69 +{0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x80,0x1F,0x80,0x1F,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x1C,0xC0,0x0F,0xC0,0x07}, // 0x6A +{0x00,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x70,0xC0,0x38,0xC0,0x1C,0xC0,0x0E,0xC0,0x06,0xC0,0x07,0xC0,0x0E,0xC0,0x1C,0xC0,0x38,0xC0,0x70,0xC0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6B +{0x00,0x00,0xC0,0x0F,0xC0,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6C +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x39,0xF0,0x7F,0x70,0x67,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6D +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x1E,0x60,0x3F,0xE0,0x31,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6E +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x3F,0xC0,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xC0,0x30,0xC0,0x3F,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6F +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x0F,0xE0,0x1F,0xE0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x18,0xE0,0x1F,0x60,0x0F,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00}, // 0x70 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x37,0xC0,0x3F,0xC0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x37,0x80,0x33,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30}, // 0x71 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3C,0xC0,0x3E,0xC0,0x23,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x72 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0xC0,0x1F,0xC0,0x00,0xC0,0x00,0xC0,0x03,0x00,0x1F,0x00,0x38,0x00,0x30,0x40,0x30,0xC0,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x73 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0xE0,0x7F,0xE0,0x7F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x7F,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x74 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x3C,0xE0,0x37,0xC0,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x75 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0,0x20,0xC0,0x30,0xC0,0x30,0x80,0x11,0x80,0x19,0x80,0x19,0x00,0x0B,0x00,0x0F,0x00,0x0F,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x76 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xC0,0x30,0xC6,0x30,0xC6,0x20,0x4E,0x60,0x4F,0x60,0x49,0x60,0x69,0x60,0x79,0xC0,0x39,0xC0,0x30,0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x77 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x70,0xC0,0x30,0x80,0x19,0x80,0x0B,0x00,0x0F,0x00,0x06,0x00,0x0F,0x80,0x1D,0x80,0x19,0xC0,0x30,0x60,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x78 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0,0x20,0xC0,0x30,0xC0,0x31,0x80,0x19,0x80,0x19,0x00,0x0B,0x00,0x0F,0x00,0x0F,0x00,0x06,0x00,0x06,0x00,0x02,0x00,0x03,0xC0,0x03,0xC0,0x01}, // 0x79 +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x3F,0xE0,0x3F,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x3F,0xE0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x7A +{0x00,0x00,0x00,0x3C,0x00,0x3E,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xC0,0x03,0xC0,0x03,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x3E,0x00,0x3C,0x00,0x00}, // 0x7B +{0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00}, // 0x7C +{0x00,0x00,0xC0,0x03,0xC0,0x07,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x3C,0x00,0x3C,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xC0,0x07,0xC0,0x03,0x00,0x00}, // 0x7D +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x43,0xE0,0x7F,0x20,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x7E +{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3F,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0xC0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0x7F +}; \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.2.bin b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.2.bin new file mode 100755 index 00000000..b170b007 Binary files /dev/null and b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.2.bin differ diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/Makefile b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/Makefile index 3b05023c..af8a6532 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/Makefile +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/Makefile @@ -1,10 +1,11 @@ MZ_FLASHER=python ../88MZ100_Flasher/88MZ100_Uart_flasher.py -ARMGCC=armgcc/bin/ +ARMGCC=/usr/bin/ CC=$(ARMGCC)arm-none-eabi-gcc AS=$(ARMGCC)arm-none-eabi-as OBJCOPY=$(ARMGCC)arm-none-eabi-objcopy + #-Wall CC_WARNING_FLAGS=-Wall -Wformat=0 -Wattributes -Wstrict-aliasing=0 CC_FlAGS=-mcpu=cortex-m3 -g -O0 -mthumb -fdata-sections -ffunction-sections -std=c99 @@ -16,10 +17,15 @@ C_EXECUTABLE :=$(C_SOURCES:.c=) COMPORT = COM12 -build: clean compile create_ota_img flash_uart_flash +build: compile only: clean compile create_ota_img uart: clean compile flash_uart +#build: clean compile create_ota_img flash_uart_flash +#only: clean compile create_ota_img +#uart: clean compile flash_uart + + compile: @mkdir -p build @$(AS) -mcpu=cortex-m3 --gdwarf-2 -mthumb-interwork -o build/startup.o startup.S @@ -40,16 +46,8 @@ compile: @$(CC) $(CC_FlAGS) -c mz100_gpt.c -o build/mz100_gpt.o @$(CC) $(CC_FlAGS) -c mz100_sleep.c -o build/mz100_sleep.o @$(CC) $(CC_FlAGS) -c mz100_uart.c -o build/mz100_uart.o -# UZLIB - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/adler32.c -o build/adler32.o - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/crc32.c -o build/crc32.o - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/defl_static.c -o build/defl_static.o - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/genlz77.c -o build/genlz77.o - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinfgzip.c -o build/tinfgzip.o - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinflate.c -o build/tinflate.o - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinfzlib.c -o build/tinfzlib.o -# UZLIB END - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c compression.c -o build/compression.o + @$(CC) $(CC_FlAGS) -c mz100_aon_ram.c -o build/mz100_aon_ram.o + @$(CC) $(CC_FlAGS) -c printf.c -o build/printf.o @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c zigbee.c -o build/zigbee.o @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c ccm.c -o build/ccm.o @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c chars.c -o build/chars.o @@ -61,10 +59,10 @@ compile: @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c timer.c -o build/timer.o @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c util.c -o build/util.o @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c gpio.c -o build/gpio.o - @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c nfc.c -o build/nfc.o @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c epd.c -o build/epd.o + @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c userinterface.c -o build/userinterface.o @$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c main.c -o build/main.o - @$(CC) $(CC_END_FLAGS) $(CC_WARNING_FLAGS) build/main.o build/adler32.o build/crc32.o build/defl_static.o build/genlz77.o build/tinfgzip.o build/tinflate.o build/tinfzlib.o build/compression.o build/zigbee.o build/ccm.o build/chars.o build/drawing.o build/powermgt.o build/syncedproto.o build/comms.o build/settings.o build/timer.o build/util.o build/gpio.o build/nfc.o build/epd.o build/mz100_sleep.o build/core_cm3.o build/mz100_ssp.o build/mz100_wdt.o build/mz100_gpio.o build/mz100_driver.o build/mz100_adc.o build/mz100_flash.o build/mz100_clock.o build/mz100_rtc.o build/mz100_pinmux.o build/mz100_pmu.o build/mz100_qspi.o build/mz100_aes.o build/mz100_gpt.o build/mz100_uart.o build/startup.o -o main.axf + @$(CC) $(CC_END_FLAGS) $(CC_WARNING_FLAGS) build/main.o build/userinterface.o build/printf.o build/mz100_aon_ram.o build/zigbee.o build/chars.o build/drawing.o build/powermgt.o build/syncedproto.o build/comms.o build/settings.o build/timer.o build/util.o build/gpio.o build/epd.o build/mz100_sleep.o build/core_cm3.o build/mz100_ssp.o build/mz100_wdt.o build/mz100_gpio.o build/mz100_driver.o build/mz100_adc.o build/mz100_flash.o build/mz100_clock.o build/mz100_rtc.o build/mz100_pinmux.o build/mz100_pmu.o build/mz100_qspi.o build/mz100_aes.o build/mz100_gpt.o build/mz100_uart.o build/startup.o -o main.axf @$(OBJCOPY) -v -O binary main.axf main.bin clean: @@ -83,4 +81,4 @@ flash_dump: @$(MZ_FLASHER) $(COMPORT) read dump.bin create_ota_img: - @$(MZ_FLASHER) img main.bin UPDT0028.BIN \ No newline at end of file + @$(MZ_FLASHER) img main.bin UPDT0028.BIN diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.c index 00dfc441..e6cb6ae2 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.c @@ -1,96 +1,32 @@ -#include -#include -#include #include "comms.h" -#include "proto.h" + +#include +//#include +#include + #include "ccm.h" +#include "proto.h" extern uint8_t Zigbee_tx_buffer(uint8_t tx_buffer[], int len); -static uint8_t packet[128]; -static uint8_t mSeq = 0; uint8_t mLastLqi = 0; int8_t mLastRSSI = 0; -uint8_t commsGetLastPacketLQI(void) -{ - return mLastLqi; +uint8_t commsGetLastPacketLQI(void) { + return mLastLqi; } -int8_t commsGetLastPacketRSSI(void) -{ - return mLastRSSI; +int8_t commsGetLastPacketRSSI(void) { + return mLastRSSI; } -static inline void __attribute__((always_inline)) macCopy(uint8_t *restrict dst, const uint8_t *restrict src) -{ - ((uint32_t *)dst)[0] = ((const uint32_t *)src)[0]; - ((uint32_t *)dst)[1] = ((const uint32_t *)src)[1]; +static inline void __attribute__((always_inline)) macCopy(uint8_t *restrict dst, const uint8_t *restrict src) { + ((uint32_t *)dst)[0] = ((const uint32_t *)src)[0]; + ((uint32_t *)dst)[1] = ((const uint32_t *)src)[1]; } -static inline bool __attribute__((always_inline)) macIsEq(const uint8_t *restrict dst, const uint8_t *restrict src) -{ - return ((uint32_t *)dst)[0] == ((const uint32_t *)src)[0] && ((uint32_t *)dst)[1] == ((const uint32_t *)src)[1]; -} - -bool commsTx(struct CommsInfo *info, bool bcast, const void *packet_in, uint32_t len) -{ - uint8_t nonce[AES_CCM_NONCE_SIZE] = {}; - struct MacFrameNormal *mfn; - struct MacFrameBcast *mfb; - uint32_t hdrSz; - char *payload; - static const struct MacFcs normalFcs = { - .frameType = FRAME_TYPE_DATA, - .panIdCompressed = 1, - .destAddrType = ADDR_MODE_LONG, - .srcAddrType = ADDR_MODE_LONG, - }; - static const struct MacFcs broadcastFcs = { - .frameType = FRAME_TYPE_DATA, - .destAddrType = ADDR_MODE_SHORT, - .srcAddrType = ADDR_MODE_LONG, - }; - - if (len > COMMS_MAX_PACKET_SZ) - return false; - - if (bcast) - { - mfb = (struct MacFrameBcast *)packet; - hdrSz = sizeof(struct MacFrameBcast); - payload = (char *)(mfb + 1); - mfb->fcs = broadcastFcs; - mfb->seq = mSeq++; - mfb->dstPan = 0xffff; - mfb->dstAddr = 0xffff; - mfb->srcPan = PROTO_PAN_ID; - macCopy(mfb->src, info->myMac); - } - else - { - mfn = (struct MacFrameNormal *)packet; - hdrSz = sizeof(struct MacFrameNormal); - payload = (char *)(mfn + 1); - mfn->fcs = normalFcs; - mfn->seq = mSeq++; - mfn->pan = PROTO_PAN_ID; - macCopy(mfn->dst, info->masterMac); - macCopy(mfn->src, info->myMac); - } - - *(uint32_t *)nonce = (*info->nextIV)++; - macCopy(nonce + sizeof(uint32_t), info->myMac); - memcpy(payload, packet_in, len); - - aesCcmEnc((void *)packet, (void *)packet, hdrSz, len, info->encrKey, nonce); - *(uint32_t *)(payload + len + AES_CCM_MIC_SIZE) = *(uint32_t *)nonce; // send nonce - - len += hdrSz; - len += AES_CCM_MIC_SIZE; - len += sizeof(uint32_t); - - return !Zigbee_tx_buffer((uint8_t *)&packet, len); +static inline bool __attribute__((always_inline)) macIsEq(const uint8_t *restrict dst, const uint8_t *restrict src) { + return ((uint32_t *)dst)[0] == ((const uint32_t *)src)[0] && ((uint32_t *)dst)[1] == ((const uint32_t *)src)[1]; } extern volatile uint8_t rx_buffer[0x400]; @@ -98,94 +34,16 @@ extern volatile uint8_t new_rx; extern volatile uint8_t new_rssi; extern volatile int rx_len; -int32_t __attribute__((noinline)) commsRx(struct CommsInfo *info, void *data, uint8_t *fromMacP) -{ - uint8_t *buf = packet, nonce[13] = {}, fromMac[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t len, minNeedLen, hdrLen = 0; - struct MacFrameFromMaster *mfm; - struct MacFrameNormal *mfn; - - // sort out how many bytes minimum are a valid packet - minNeedLen = sizeof(struct MacFrameFromMaster); // mac header - minNeedLen += sizeof(uint8_t); // packet type - minNeedLen += AES_CCM_MIC_SIZE; // MIC - minNeedLen += sizeof(uint32_t); // nonce counter - minNeedLen += 2 * sizeof(uint8_t); // RSSI/LQI - - if (!new_rx) - return COMMS_RX_ERR_NO_PACKETS; - - // some basic checks - mfm = (struct MacFrameFromMaster *)rx_buffer; - if (rx_len >= sizeof(packet) || rx_len < minNeedLen || mfm->fcs.frameType != FRAME_TYPE_DATA || - mfm->fcs.secure || mfm->fcs.frameVer || mfm->fcs.destAddrType != ADDR_MODE_LONG || !mfm->fcs.panIdCompressed || - (mfm->fcs.srcAddrType != ADDR_MODE_LONG && mfm->fcs.srcAddrType != ADDR_MODE_SHORT) || - mfm->pan != PROTO_PAN_ID || !macIsEq(mfm->dst, info->myMac)) - { - new_rx = 0; - return COMMS_RX_ERR_INVALID_PACKET; - } - - // copy out and release buffer - memcpy(buf, &rx_buffer, len = rx_len - 2 * sizeof(uint8_t)); - mLastLqi = rx_buffer[len + 0]; - mLastRSSI = rx_buffer[len + 1]; - - mfm = (struct MacFrameFromMaster *)buf; - mfn = (struct MacFrameNormal *)buf; - new_rx = 0; - - // sort out header len, copy mac into nonce - if (mfm->fcs.srcAddrType == ADDR_MODE_LONG) - { - - macCopy(fromMac, mfn->src); - hdrLen = sizeof(struct MacFrameNormal); - - // re-verify needed length - minNeedLen -= sizeof(struct MacFrameFromMaster); - minNeedLen += sizeof(struct MacFrameNormal); - - if (rx_len < minNeedLen) - return COMMS_RX_ERR_INVALID_PACKET; - } - else if (mfm->fcs.srcAddrType == ADDR_MODE_SHORT) - { - - macCopy(fromMac, info->masterMac); - hdrLen = sizeof(struct MacFrameFromMaster); - } - - // sort out the nonce - macCopy(nonce + sizeof(uint32_t), fromMac); - *(uint32_t *)nonce = *(uint32_t *)(buf + len - sizeof(uint32_t)); - - // decrypt and auth - len -= hdrLen + AES_CCM_MIC_SIZE + sizeof(uint32_t); - - if (!aesCcmDec(buf, buf, hdrLen, len, info->encrKey, nonce)) - return COMMS_RX_ERR_MIC_FAIL; - - if (fromMacP) - macCopy(fromMacP, fromMac); - - memcpy(data, buf + hdrLen, len); - - return len; +int32_t __attribute__((noinline)) commsRxUnenc(void *data) { + if (!new_rx) + return COMMS_RX_ERR_NO_PACKETS; + memcpy(data, (uint8_t*)&rx_buffer, rx_len); + mLastLqi = 255 - new_rssi; + mLastRSSI = new_rssi; + new_rx = 0; + return rx_len; } -int32_t __attribute__((noinline)) commsRxUnenc(void *data) -{ - if (!new_rx) - return COMMS_RX_ERR_NO_PACKETS; - memcpy(data, &rx_buffer, rx_len); - mLastLqi = 255 - new_rssi; - mLastRSSI = new_rssi; - new_rx = 0; - return rx_len; -} - -void commsTxNoCpy(uint8_t *packetp) -{ - Zigbee_tx_buffer((uint8_t *)&packetp[1], (packetp[0] - 2)); +void commsTxNoCpy(uint8_t *packetp) { + Zigbee_tx_buffer((uint8_t *)&packetp[1], (packetp[0] - 2)); } diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.h index f06d30dd..a9c4d17b 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.h @@ -4,12 +4,6 @@ #include #include "ccm.h" -struct CommsInfo { - const uint8_t *myMac; - const uint8_t *masterMac; - const void *encrKey; - uint32_t *nextIV; -}; extern uint8_t mLastLqi; extern int8_t mLastRSSI; @@ -23,8 +17,6 @@ extern int8_t mLastRSSI; #define COMMS_MAX_PACKET_SZ (127 /* max phy len */ - 21 /* max mac frame with panID compression */ - 2 /* FCS len */ - AES_CCM_MIC_SIZE - COMMS_IV_SIZE) -bool commsTx(struct CommsInfo *info, bool bcast, const void *packet, uint32_t len); -int32_t commsRx(struct CommsInfo *info, void *data, uint8_t *fromMac); //returns length or COMMS_RX_ERR_* uint8_t commsGetLastPacketLQI(void); int8_t commsGetLastPacketRSSI(void); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.c index b5b7a04a..0bc5d1d7 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.c @@ -1,7 +1,7 @@ #include "compression.h" #include "uzlib/src/uzlib.h" -#include +//#include #include #include #include diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.h index dc74075b..b059a007 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.h @@ -1,7 +1,7 @@ #pragma once #include "uzlib/src/uzlib.h" -#include +//#include #include #include #include diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.c index 187c733d..20b01fd7 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.c @@ -2,6 +2,7 @@ #include #include +#include "printf.h" #include "board.h" #include "eeprom.h" @@ -11,366 +12,22 @@ #include "util.h" #include "epd.h" -#define COMPRESSION_BITPACKED_3x5_to_7 0x62700357 // 3 pixels of 5 possible colors in 7 bits -#define COMPRESSION_BITPACKED_5x3_to_8 0x62700538 // 5 pixels of 3 possible colors in 8 bits -#define COMPRESSION_BITPACKED_3x6_to_8 0x62700368 // 3 pixels of 6 possible colors in 8 bits - -struct BitmapFileHeader -{ - uint8_t sig[2]; - uint32_t fileSz; - uint8_t rfu[4]; - uint32_t dataOfst; - uint32_t headerSz; // 40 - int32_t width; - int32_t height; - uint16_t colorplanes; // must be one - uint16_t bpp; - uint32_t compression; - uint32_t dataLen; // may be 0 - uint32_t pixelsPerMeterX; - uint32_t pixelsPerMeterY; - uint32_t numColors; // if zero, assume 2^bpp - uint32_t numImportantColors; -}; struct BitmapClutEntry { uint8_t b, g, r, x; }; -struct BitmapDrawInfo -{ - // dimensions - uint16_t w, h, effectiveW, effectiveH, stride /* 0 -> 1, 5 - >7, 255 -> 256 */; - uint8_t numColorsM1; - - // data start - uint32_t dataAddr; - - // compression state - uint8_t packetPixelDivVal; - uint8_t packetNumPixels; - uint8_t packetBitSz; - uint8_t packetBitMask; // derived from the above - - // flags - uint8_t bpp : 4; - uint8_t bottomUp : 1; -}; uint8_t mPassNo = 0; -static const uint8_t mColorMap[][6] = { - // colors are: B, DG, G, LG, W, R - // phase 0 (LUTS: B:W:R:G, purpose: BWR, prepare greys) - {1, 1, 1, 1, 0, 0}, // lo plane (B) - - {0, 0, 0, 0, 0, 1} // hi plane (R) -}; - static uint8_t mClutMap[256]; static uint8_t mClutMapRed[256]; -static struct BitmapDrawInfo mDrawInfo; - -static uint32_t drawPrvParseHeader(uint32_t addr) // return clut addr or zero on error -{ - /*struct BitmapFileHeader bmph; - uint16_t packetsPerRow; - - addr += sizeof(struct EepromImageHeader); - eepromRead(addr, &bmph, sizeof(bmph)); - - if (bmph.sig[0] != 'B' || bmph.sig[1] != 'M') - goto fail; - - if (bmph.colorplanes != 1) - goto fail; - - if ((&bmph.headerSz - 40)) // < 40 - goto fail; - - if (bmph.bpp > 8) - goto fail; - - mDrawInfo.bpp = bmph.bpp; - - if (!(&bmph.headerSz - 257)) // >= 257 - goto fail; - - if ((&bmph.numColors)) - mDrawInfo.numColorsM1 = (uint8_t)bmph.numColors - (uint8_t)1; - else - mDrawInfo.numColorsM1 = (uint8_t)((uint8_t)1 << (uint8_t)mDrawInfo.bpp) - (uint8_t)1; - - if (!(&bmph.height)) - goto fail; - - if ((&bmph.width - 1) || !(&bmph.width - 0xffff)) - goto fail; - mDrawInfo.w = bmph.width; - - if ((&bmph.height) < 0) - { - if ((&bmph.height + 0xffff)) // carries if val too negative - goto fail; - mDrawInfo.h = -bmph.height; - mDrawInfo.bottomUp = false; - } - else - { - if (!(&bmph.headerSz - 0xffff)) // no carry if val too big - goto fail; - mDrawInfo.h = bmph.height; - mDrawInfo.bottomUp = true; - } - - if (bmph.compression) - { - printf("compression is not supported ;("); - goto fail; - } - - mDrawInfo.packetPixelDivVal = 0; - mDrawInfo.packetNumPixels = 1; - if (mDrawInfo.bpp > 1) - { - mDrawInfo.packetBitSz = 2; - } - else - { - mDrawInfo.packetBitSz = 1; // mDrawInfo.bpp; - } - - // mDrawInfo.stride = mathPrvDiv32x8(mathPrvMul16x8((mDrawInfo.w + mDrawInfo.packetNumPixels - 1), mDrawInfo.packetBitSz) + 31, 32) * 4UL; - // mDrawInfo.packetBitMask = (uint8_t)(((uint8_t)1) << (uint8_t)mDrawInfo.packetBitSz) - (uint8_t)1; - - packetsPerRow = (mDrawInfo.w + mDrawInfo.packetNumPixels - 1) / (mDrawInfo.packetNumPixels); - mDrawInfo.stride = (((packetsPerRow * mDrawInfo.packetBitSz) + 31) / 32) * 4UL; - mDrawInfo.packetBitMask = (uint8_t)(((uint8_t)1) << (uint8_t)mDrawInfo.packetBitSz) - (uint8_t)1; - - // calc effective size - mDrawInfo.effectiveH = (mDrawInfo.h > SCREEN_HEIGHT) ? SCREEN_HEIGHT : mDrawInfo.h; - mDrawInfo.effectiveW = (mDrawInfo.w > SCREEN_WIDTH) ? SCREEN_WIDTH : mDrawInfo.w; - - // calc addrs - mDrawInfo.dataAddr = addr + bmph.dataOfst; - return addr + bmph.dataOfst - sizeof(struct BitmapClutEntry) * (1 + mDrawInfo.numColorsM1); - -fail: - printf("Tried to parse the bmp header, didn't work...");*/ - return 0; -} - -static void drawPrvLoadAndMapClut(uint32_t clutAddr) -{ - /*struct BitmapClutEntry clut; - uint8_t i; - - // convert clut to our understanding of color - i = 0; - do - { - uint8_t entry; - - eepromRead(clutAddr, &clut, sizeof(clut)); - clutAddr += sizeof(struct BitmapClutEntry); - - if (SCREEN_EXTRA_COLOR_INDEX >= 0 && clut.r == 0xff && (clut.g == 0xff || clut.g == 0) && clut.b == 0) // yellow/red - entry = SCREEN_EXTRA_COLOR_INDEX; - else - { - uint16_t intensity = 0; - - intensity += (0x37 * clut.r); - intensity += (0xB7 * clut.g); - intensity += (0x12 * clut.b); - // adds up to 0xff00 -> fix it - intensity += (uint8_t)(intensity >> 8); - - entry = (intensity * SCREEN_NUM_GREYS) >> 16; - entry += SCREEN_FIRST_GREY_IDX; - } - // printf("mapped clut %u (%d %d %d) -> %d\n", i, clut.r, clut.g, clut.b, entry); - mClutMap[i] = entry; - } while (i++ != mDrawInfo.numColorsM1); - - // replicate clut down if not a full 256-entry clut - if (mDrawInfo.bpp != 8) - { - uint8_t num = (uint8_t)((uint8_t)1 << (uint8_t)mDrawInfo.bpp); - - // we can use the fact that our memcpy always copies forward - memcpy(mClutMap + num, mClutMap, (uint8_t)256 - (uint8_t)num); - }*/ -} - -static void drawPrvDecodeImageOnce(void) -{ - /*uint8_t rowBuf[SCREEN_WIDTH]; - uint16_t er, c; - if (mDrawInfo.bottomUp) - er = mDrawInfo.effectiveH - 1; - else - er = 0; - while (1) - { // we account differently for loop gets compiled worse - uint8_t inIdx = 0, bitpoolInUsed = 0, bitpoolIn = 0; - uint16_t nBytesOut = 0; - -#if SCREEN_TX_BPP == 4 - uint8_t txPrev = 0; - bool emit = false; -#else - uint8_t bitpoolOutUsedUsed = 0; - uint16_t bitpoolOut = 0; -#endif - // get a row - epdDeselect(); - eepromRead((er * mDrawInfo.stride) + mDrawInfo.dataAddr, rowBuf, mDrawInfo.stride); - epdSelect(); - // convert to our format - c = mDrawInfo.effectiveW; - do - { - // uartTx('.'); - uint8_t packet, packetIdx, packetMembers = mDrawInfo.packetNumPixels; - - if (bitpoolInUsed >= mDrawInfo.packetBitSz) - { - bitpoolInUsed -= mDrawInfo.packetBitSz; - packet = bitpoolIn >> bitpoolInUsed; - } - else - { - uint8_t packetBitSz = mDrawInfo.packetBitSz; - uint8_t t = rowBuf[inIdx++]; - - packet = (bitpoolIn << (packetBitSz - bitpoolInUsed)) | (t >> (8 - (packetBitSz - bitpoolInUsed))); - bitpoolInUsed += 8 - packetBitSz; - - bitpoolIn = t; - } - packet &= mDrawInfo.packetBitMask; - - // val is now a packet - unpack it - if (packetMembers > c) - packetMembers = c; - - for (packetIdx = 0; packetIdx < packetMembers; packetIdx++) - { - uint8_t val; - - // extract - if (mDrawInfo.packetPixelDivVal) - { - val = packet % mDrawInfo.packetPixelDivVal; - packet /= mDrawInfo.packetPixelDivVal; - } - else - val = packet; - - // map - val = mClutMap[val]; - -// get bits out -#if SCREEN_TX_BPP == 4 - - if (emit) - { - emit = false; - ByteDecode(txPrev | val); - nBytesOut++; - txPrev = 0; - } - else - { - emit = true; - txPrev = val << 4; - } - -#else - bitpoolOut <<= SCREEN_TX_BPP; - bitpoolOut |= val; - bitpoolOutUsedUsed += SCREEN_TX_BPP; - if (bitpoolOutUsedUsed >= 8) - { - ByteDecode(bitpoolOut >> (bitpoolOutUsedUsed -= 8)); - bitpoolOut &= (1 << bitpoolOutUsedUsed) - 1; - nBytesOut++; - } -#endif - } - c -= packetMembers; - } while (c); - -#if SCREEN_TX_BPP == 4 - - if (emit) - { - ByteDecode(txPrev); - nBytesOut++; - } - -#else - - if (bitpoolOutUsedUsed) - { - ByteDecode(bitpoolOut); - nBytesOut++; - } - -#endif - - // if we did not produce enough bytes, do so - nBytesOut = ((long)SCREEN_WIDTH * SCREEN_TX_BPP + 7) / 8 - nBytesOut; - while (nBytesOut--) - ByteDecode(SCREEN_BYTE_FILL); - - // update row - if (mDrawInfo.bottomUp) - { - if (er) - er--; - else - break; - } - else - { - er++; - if (er == mDrawInfo.effectiveH) - break; - } - } - - // fill the rest of the screen - for (er = mDrawInfo.effectiveH - SCREEN_HEIGHT; er; er--) - { - for (c = ((long)SCREEN_WIDTH * SCREEN_TX_BPP + 7) / 8; c; c--) - { - ByteDecode(SCREEN_BYTE_FILL); - } - }*/ -} - -static uint8_t prev, step = 0; - -void ByteDecode(uint8_t byte) -{ - /*prev <<= 2; - prev |= (mColorMap[mPassNo][byte >> 4] << 1) | mColorMap[mPassNo][byte & 0x0f]; - if (++step == 4) - { - step = 0; - Display_Write_byte(prev); - }*/ -} void drawImageAtAddress(uint32_t addr, uint8_t lut) { struct EepromImageHeader *eih = (struct EepromImageHeader *)mClutMap; eepromRead(addr, mClutMap, sizeof(struct EepromImageHeader)); - uint8_t prevVal = 0; switch (eih->dataType) { case DATATYPE_IMG_RAW_1BPP: @@ -430,34 +87,6 @@ void drawImageAtAddress(uint32_t addr, uint8_t lut) display_send_stop(); epd_refresh_and_sleep(); break; - case DATATYPE_IMG_BMP:; - uint32_t clutAddr; - printf("sending BMP to EPD - "); - /*clutAddr = drawPrvParseHeader(addr); - if (!clutAddr) - return; - drawPrvLoadAndMapClut(clutAddr); - - epdSetup(); - if (lut) - selectLUT(lut); - mPassNo = 0; - beginFullscreenImage(); - beginWriteFramebuffer(EPD_COLOR_BLACK); - prev = 0; - step = 0; - drawPrvDecodeImageOnce(); - endWriteFramebuffer(); - mPassNo++; - beginFullscreenImage(); - beginWriteFramebuffer(EPD_COLOR_RED); - prev = 0; - step = 0; - drawPrvDecodeImageOnce(); - endWriteFramebuffer();*/ - - printf(" complete.\n"); - break; default: // prevent drawing from an unknown file image type printf("Image with type 0x%02X was requested, but we don't know what to do with that currently...\n", eih->dataType); return; diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.c old mode 100644 new mode 100755 index 3ba31c32..7998eccc --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.c @@ -1,431 +1,753 @@ -#include -#include -#include -#include "core_cm3.h" -#include "main.h" #include "epd.h" -#include "mz100_gpio.h" -#include "mz100_ssp.h" -#include "mz100_pinmux.h" -#include "mz100_clock.h" -#include "mz100_wdt.h" -#include "util.h" + +#include +#include +//#include +#include "printf.h" +#include +#include + +#include "12x20_horizontal_LSB_1.h" +#include "core_cm3.h" #include "gpio.h" +#include "main.h" +#include "mz100_clock.h" +#include "mz100_gpio.h" +#include "mz100_pinmux.h" +#include "mz100_ssp.h" +#include "mz100_wdt.h" +#include "stdarg.h" +#include "util.h" -void epd_reset() -{ - uint8_t v0 = 5; - while (1) - { - GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH); - delay(100); - GPIO_WritePinOutput(EPD_RESET, GPIO_IO_LOW); - delay(3000); - GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH); - delay(3000); - if (GPIO_ReadPinLevel(EPD_BUSY)) - break; - v0--; - if (!v0) - { - printf("EPD reset failure\r\n"); - break; - } - } - delay(5000); +#define EPD_PANEL_SETTING 0x00 +#define EPD_POWER_SETTING 0x01 +#define EPD_POWER_OFF 0x02 +#define EPD_POWER_OFF_SEQUENCE 0x03 +#define EPD_POWER_ON 0x04 +#define EPD_BOOSTER_SOFT_START 0x06 +#define EPD_DEEP_SLEEP 0x07 +#define EPD_START_DATA 0x10 +#define EPD_DATA_STOP 0x11 +#define EPD_REFRESH 0x12 +#define EPD_IMAGE_PROCESS 0x13 +#define EPD_LUT_VCOM 0x20 +#define EPD_LUT_B 0x21 +#define EPD_LUT_W 0x22 +#define EPD_LUT_G1 0x23 +#define EPD_LUT_G2 0x24 +#define EPD_LUT_R0 0x25 +#define EPD_LUT_R1 0x26 +#define EPD_LUT_R2 0x27 +#define EPD_LUT_R3 0x28 +#define EPD_LUT_XON 0x29 +#define EPD_PLL_CONTROL 0x30 +#define EPD_TEMP_CALIB 0x40 +#define EPD_TEMP_SELECT 0x41 +#define EPD_TEMP_WRITE 0x42 +#define EPD_TEMP_READ 0x43 +#define EPD_VCOM_DATA_INTERVAL 0x50 +#define EPD_LPD 0x51 +#define EPD_TCON_SET 0x60 +#define EPD_TRES 0x61 +#define EPD_SPI_FLASH_CONTROL 0x65 +#define EPD_REVISION 0x70 +#define EPD_GET_STATUS 0x71 +#define EPD_AUTOMEASURE_VCOM 0x80 +#define EPD_READ_VCOM 0x81 +#define EPD_VCOM_DC_SET 0x82 +#define EPD_SET_WINDOW 0x90 + +#define EPD_WAKE_EEPROM 0xAB +#define EPD_EEPROM_SLEEP 0xB9 +#define EPD_UNKNOWN_1 0xE5 + +static uint8_t EPDtempBracket = 0; + +struct epd_colorlutpart { + uint8_t repeat; + uint8_t lvl0 : 4; + uint8_t lvl1 : 4; + uint8_t lvl2 : 4; + uint8_t lvl3 : 4; + uint8_t lvl4 : 4; + uint8_t lvl5 : 4; + uint8_t lvl6 : 4; + uint8_t lvl7 : 4; + uint8_t length[8]; +} __packed; + +struct epd_colorlut { + struct epd_colorlutpart part[20]; +} __packed; + +struct epd_vcomlutpart { + uint8_t repeat; + uint8_t lvl0 : 2; + uint8_t lvl1 : 2; + uint8_t lvl2 : 2; + uint8_t lvl3 : 2; + uint8_t lvl4 : 2; + uint8_t lvl5 : 2; + uint8_t lvl6 : 2; + uint8_t lvl7 : 2; + uint8_t length[8]; +} __packed; + +struct epd_vcomlut { + struct epd_vcomlutpart part[20]; +} __packed; + +struct epd_xonlutpart { + uint8_t repeat; + uint8_t lvl0 : 1; + uint8_t lvl1 : 1; + uint8_t lvl2 : 1; + uint8_t lvl3 : 1; + uint8_t lvl4 : 1; + uint8_t lvl5 : 1; + uint8_t lvl6 : 1; + uint8_t lvl7 : 1; + uint8_t length[8]; +} __packed; + +struct epd_xonlut { + struct epd_xonlutpart part[20]; +} __packed; + +void interleaveColor(uint8_t b) { + b ^= 0xFF; + uint8_t b_out = 0; + for (uint8_t shift = 0; shift < 4; shift++) { + b_out = 0; + if ((b >> 2 * shift) & 0x01) b_out |= 0x30; + if ((b >> 2 * shift) & 0x02) b_out |= 0x03; + display_tx_byte(b_out); + } } -void EPD_cmd(char a1) -{ - unsigned int v1 = 0; +void epdWrite(uint8_t reg, uint8_t len, ...) { + va_list valist; + va_start(valist, len); + epd_pin_enable(1); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); + GPIO_WritePinOutput(EPD_DC, GPIO_IO_LOW); + SSP_SendData(SSP2_ID, reg); + for (int i = 0; i < 0xF; ++i) + __ISB(); + GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH); + for (uint8_t i = 0; i < len; i++) { + SSP_SendData(SSP2_ID, va_arg(valist, int)); + } - GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); - GPIO_WritePinOutput(EPD_DC, GPIO_IO_LOW); - do - { - if ((a1 & 0x80) != 0) - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH); - else - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); - a1 *= 2; - v1++; - delay_us(1); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); - delay_us(1); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); - } while (v1 < 8); - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); - GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH); - GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); - delay(1000); + for (int j = 0; j < 0xF; ++j) + __ISB(); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); + epd_pin_enable(0); + va_end(valist); } -void EPD_data(char a1) -{ - unsigned int v1 = 0; - - GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); - do - { - if ((a1 & 0x80) != 0) - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH); - else - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); - a1 *= 2; - v1++; - delay_us(1); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); - delay_us(1); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); - } while (v1 < 8); - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); - GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); - delay(1000); +void epd_reset() { + uint8_t v0 = 5; + printf("Resetting..."); + while (1) { + GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH); + delay(100); + GPIO_WritePinOutput(EPD_RESET, GPIO_IO_LOW); + delay(3000); + GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH); + delay(3000); + if (GPIO_ReadPinLevel(EPD_BUSY)) + break; + v0--; + if (!v0) { + printf("EPD reset failure\r\n"); + break; + } + } + delay(5000); + printf(" Reset complete\n"); } -void spi_soft_send_byte(char a1) -{ - uint8_t v2 = 0; - do - { - if ((a1 & 0x80) != 0) - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH); - else - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); - delay_us(1); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); - delay_us(1); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); - a1 *= 2; - v2++; - } while (v2 < 8); - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); - delay_us(1); +void EPD_cmd(char a1) { + epd_pin_enable(1); + + GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); + GPIO_WritePinOutput(EPD_DC, GPIO_IO_LOW); + SSP_SendData(SSP2_ID, a1); + for (int i = 0; i < 0xF; ++i) + __ISB(); + + epd_pin_enable(0); + + GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); } -void BUSY_wait(unsigned int a1) -{ - unsigned int v2 = 0; - while (GPIO_ReadPinLevel(EPD_BUSY) == GPIO_IO_LOW) - { - delay(10000); - v2++; - if (v2 > a1) - break; - if (!(20 * (v2 % 1000 / 10))) - WDT_RestartCounter(); - } +void EPD_data(char a1) { + epd_pin_enable(1); + + GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); + SSP_SendData(SSP2_ID, a1); + for (int i = 0; i < 0xF; ++i) + __ISB(); + + epd_pin_enable(0); + + GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); } -void spi_soft_read_buffer(char a1, uint16_t a2, uint8_t *a3, unsigned int a4) -{ - char v9; - unsigned int v10; - - GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); - GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW); - spi_soft_send_byte(3); - spi_soft_send_byte(a1); - spi_soft_send_byte(a2 >> 8); - spi_soft_send_byte(a2); - delay_us(10); - for (int i = 0; i < a4; i = (uint8_t)(i + 1)) - { - v9 = 0; - v10 = 0; - do - { - v9 *= 2; - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); - delay_us(5); - if (GPIO_ReadPinLevel(EPD_MISO)) - v9 |= 1u; - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); - delay_us(5); - v10++; - } while (v10 < 8); - delay_us(5); - *a3++ = v9; - } - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); - GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH); +void spi_soft_send_byte(char a1) { + uint8_t v2 = 0; + do { + if ((a1 & 0x80) != 0) + GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH); + else + GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); + delay_us(1); + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); + delay_us(1); + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); + a1 *= 2; + v2++; + } while (v2 < 8); + GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); + delay_us(1); } -int spi_soft_read_byte() -{ - int v0; - unsigned int v1; - - v0 = 0; - GPIO_WritePinOutput(EPD_BS, GPIO_IO_HIGH); - GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); - delay_us(1); - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); - delay_us(1); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); - delay_us(1); - GPIO_SetPinDir(EPD_MOSI, GPIO_INPUT); - GPIO_PinMuxFun(EPD_MOSI, 0); - delay_us(3); - v1 = 0; - do - { - v0 = (uint8_t)(2 * v0); - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); - if (GPIO_ReadPinLevel(EPD_MOSI)) - v0 |= 1u; - GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); - delay_us(1); - v1++; - } while (v1 < 8); - GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT); - GPIO_PinMuxFun(EPD_MOSI, 0); - GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); - delay_us(1); - GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); - delay_us(1); - GPIO_WritePinOutput(EPD_BS, GPIO_IO_LOW); - return v0; +void BUSY_wait(unsigned int a1) { + unsigned int v2 = 0; + while (GPIO_ReadPinLevel(EPD_BUSY) == GPIO_IO_LOW) { + delay(10000); + v2++; + if (v2 > a1) + break; + if (((v2 % 1000) / 10) == 0) + WDT_RestartCounter(); + } } -void epd_read_write_30() -{ - uint8_t v0; - uint8_t v1; - uint8_t v4; - uint8_t v5[12]; - uint8_t v6[12]; - uint8_t v7[40]; +void spi_soft_read_buffer(char a1, uint16_t readaddress, uint8_t *target, uint16_t length) { + char v9; + unsigned int v10; - EPD_cmd(101); - EPD_data(1); - delay_us(1000); - spi_soft_read_buffer(0, 25002, v7, 10); - delay_us(1000); - spi_soft_read_buffer(0, 25039, v6, 10); - delay_us(1000); - EPD_cmd(101); - EPD_data(0); - EPD_cmd(64); - BUSY_wait(0xAu); - v0 = spi_soft_read_byte(); - v1 = (uint8_t)(2 * v0) + ((uint8_t)spi_soft_read_byte() >> 7); - for (int i = 0; i < 9; i++) - v5[i] = (((char)v1 - (uint8_t)v7[i]) & 0x80) != 0; - for (int j = 0; j < 9; j++) - { - v4 = v6[j]; - if (v5[j] == 1) - break; - } - EPD_cmd(0x30); - EPD_data(v4); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); + GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW); + spi_soft_send_byte(3); + spi_soft_send_byte(a1); + spi_soft_send_byte(readaddress >> 8); + spi_soft_send_byte(readaddress); + delay_us(5); + for (uint16_t i = 0; i < length; i++) { + v9 = 0; + v10 = 0; + do { + v9 *= 2; + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); + delay_us(1); + if (GPIO_ReadPinLevel(EPD_MISO)) + v9 |= 1u; + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); + delay_us(1); + v10++; + } while (v10 < 8); + delay_us(1); + *target++ = v9; + } + + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); + GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH); } -void epd_read_write_82() -{ - uint8_t v0; - int v1; - uint8_t v4; - uint8_t v5[12]; - uint8_t v6[12]; - uint8_t v7[32]; +int spi_soft_read_byte() { + int v0; + unsigned int v1; - EPD_cmd(101); - EPD_data(1); - delay_us(1000); - spi_soft_read_buffer(0, 25002, v7, 10); - spi_soft_read_buffer(0, 25049, v6, 10); - delay_us(1000); - EPD_cmd(101); - EPD_data(0); - EPD_cmd(0x40); - BUSY_wait(0xAu); - v0 = spi_soft_read_byte(); - v1 = (char)(2 * v0 + ((unsigned int)spi_soft_read_byte() >> 7)); - for (int i = 0; i < 9; i++) - v5[i] = ((v1 - (uint8_t)v7[i]) & 0x80) != 0; - for (int j = 0; j < 9; j++) - { - v4 = v6[j]; - if (v5[j] == 1) - break; - } - EPD_cmd(0x82); - EPD_data(v4); -} -void epd_send_init() -{ - GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); - delay(1000); - EPD_cmd(4); - BUSY_wait(0x32u); - EPD_cmd(1); - EPD_data(55); - EPD_data(0); - EPD_data(5); - EPD_data(5); - EPD_cmd(0); - EPD_data(203); - EPD_data(8); - EPD_cmd(229); - EPD_data(3); - EPD_cmd(3); - EPD_data(0); - EPD_cmd(6); - EPD_data(199); - EPD_data(204); - EPD_data(45); - EPD_cmd(48); - EPD_data(60); - EPD_cmd(65); - EPD_data(0); - EPD_cmd(80); - EPD_data(119); - EPD_cmd(96); - EPD_data(34); - EPD_cmd(97); - EPD_data(2); - EPD_data(128); - EPD_data(1); - EPD_data(128); - epd_read_write_82(); - EPD_cmd(2); - BUSY_wait(0x32u); + v0 = 0; + GPIO_WritePinOutput(EPD_BS, GPIO_IO_HIGH); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); + delay_us(1); + GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH); + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); + delay_us(1); + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); + delay_us(1); + GPIO_SetPinDir(EPD_MOSI, GPIO_INPUT); + GPIO_PinMuxFun(EPD_MOSI, 0); + delay_us(3); + v1 = 0; + do { + v0 = (uint8_t)(2 * v0); + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH); + if (GPIO_ReadPinLevel(EPD_MOSI)) + v0 |= 1u; + GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW); + delay_us(1); + v1++; + } while (v1 < 8); + GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT); + GPIO_PinMuxFun(EPD_MOSI, 0); + GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW); + delay_us(1); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); + delay_us(1); + GPIO_WritePinOutput(EPD_BS, GPIO_IO_LOW); + return v0; } -void init_GPIO_EPD() -{ - SSP_CFG_Type v0; - SPI_Param_Type spiParaStruct; - GPIO_PinMuxFun(EPD_MOSI, 0); - GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT); - GPIO_PinMuxFun(EPD_CLK, 0); - GPIO_SetPinDir(EPD_CLK, GPIO_OUTPUT); - GPIO_PinMuxFun(EPD_CS, 0); - GPIO_SetPinDir(EPD_CS, GPIO_OUTPUT); - GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); - GPIO_PinMuxFun(EPD_BUSY, 0); - GPIO_SetPinDir(EPD_BUSY, GPIO_INPUT); - GPIO_PinModeConfig(EPD_BUSY, PINMODE_PULLUP); - GPIO_PinMuxFun(EPD_RESET, 0); - GPIO_SetPinDir(EPD_RESET, GPIO_OUTPUT); - GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH); - GPIO_PinMuxFun(EPD_DC, 0); - GPIO_SetPinDir(EPD_DC, GPIO_OUTPUT); - GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH); - GPIO_PinMuxFun(EPD_BS, 0); - GPIO_SetPinDir(EPD_BS, GPIO_OUTPUT); - GPIO_WritePinOutput(EPD_BS, GPIO_IO_LOW); - GPIO_PinMuxFun(EPD_HLT_CTRL, 0); - GPIO_SetPinDir(EPD_HLT_CTRL, GPIO_OUTPUT); - GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH); - GPIO_PinMuxFun(EPD_MISO, 0); - GPIO_SetPinDir(EPD_MISO, GPIO_INPUT); - GPIO_PinModeConfig(EPD_MISO, PINMODE_DEFAULT); - memset(&v0, 0, 9); - v0.timeOutVal = 0; - SSP_Init(SSP2_ID, &v0); - spiParaStruct.spiClkPhase = SPI_SCPHA_1; - spiParaStruct.spiClkPolarity = SPI_SCPOL_LOW; - SPI_Config(SSP2_ID, &spiParaStruct); - CLK_I2SClkSrc(CLK_I2S_XTAL32M); - CLK_SSPClkSrc(CLK_SSP_ID_2, CLK_SSP_I2S); - CLK_I2SClkDivider(1, 1); +uint8_t getTempBracket() { + uint8_t v0; + uint8_t v1; + uint8_t temptable[40]; + + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(1); + delay_us(1000); + spi_soft_read_buffer(0, 25002, temptable, 10); + delay_us(1000); + delay_us(1000); + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(0); + + EPD_cmd(EPD_TEMP_CALIB); + BUSY_wait(0xAu); + v0 = spi_soft_read_byte(); + v1 = (uint8_t)(2 * v0) + ((uint8_t)spi_soft_read_byte() >> 7); + + uint8_t bracket = 0; + for (int i = 0; i < 9; i++) { + if ((((char)v1 - (uint8_t)temptable[i]) & 0x80) != 0) { + bracket = i; + break; + } + } + return bracket; } -void epd_refresh_and_sleep() -{ - EPD_cmd(0x12); - delay(100000); - do_sleeped_epd_refresh(); - init_GPIO_EPD(); - epd_reset(); - epd_reset(); - EPD_cmd(1); - EPD_data(2); - EPD_data(0); - EPD_data(0); - EPD_data(0); - delay_us(500000); - EPD_cmd(2); - delay_us(1000000); - BUSY_wait(0x32u); - EPD_cmd(0x65); - EPD_data(1); - GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW); - spi_soft_send_byte(0xB9); - GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH); - EPD_cmd(0x65); - EPD_data(0); - EPD_cmd(7); - EPD_data(0xA5); +void loadFrameRatePLL(uint8_t bracket) { + uint8_t pllvalue; + uint8_t plltable[12]; + + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(1); + delay_us(1000); + spi_soft_read_buffer(0, 25039, plltable, 10); + delay_us(1000); + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(0); + + pllvalue = plltable[bracket]; + + EPD_cmd(EPD_PLL_CONTROL); + EPD_data(pllvalue); } -void epd_pin_enable(int a1) -{ - if (a1) - { - GPIO_PinMuxFun(EPD_CLK, GPIO22_SSP2_SCK); - GPIO_PinMuxFun(EPD_MOSI, GPIO12_SSP2_TXD); - GPIO_PinMuxFun(EPD_MISO, GPIO13_SSP2_RXD); - SSP_Enable(SSP2_ID); - } - else - { - SSP_Disable(SSP2_ID); - GPIO_PinMuxFun(EPD_MOSI, 0); - GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT); - GPIO_PinMuxFun(EPD_CLK, 0); - GPIO_SetPinDir(EPD_CLK, GPIO_OUTPUT); - GPIO_PinMuxFun(EPD_MISO, 0); - GPIO_SetPinDir(EPD_MISO, GPIO_INPUT); - GPIO_PinModeConfig(EPD_MISO, PINMODE_DEFAULT); - } +extern void dump(const uint8_t *a, const uint16_t l); + +void loadTempVCOMDC(uint8_t bracket) { + uint8_t vcomvalue; + uint8_t vcomtable[12]; + + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(1); + delay_us(1000); + spi_soft_read_buffer(0, 25049, vcomtable, 10); + delay_us(1000); + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(0); + + vcomvalue = vcomtable[bracket]; + + EPD_cmd(EPD_VCOM_DC_SET); + EPD_data(vcomvalue); } -void display_tx_byte(uint8_t data) -{ - SSP_SendData(SSP2_ID, data); - for (int i = 0; i < 0xF; ++i) - __ISB(); +uint8_t *loadLUT(uint8_t index, uint8_t bracket) { + uint16_t adr = 0; + uint16_t len = 0; + uint8_t *lutBuffer; + switch (index) { + case EPD_LUT_VCOM: + // VCOM LUT + adr = 20800 + (220 * bracket); + len = 220; + break; + case EPD_LUT_B: + case EPD_LUT_W: + case EPD_LUT_G1: + case EPD_LUT_G2: + case EPD_LUT_R0: + case EPD_LUT_R1: + case EPD_LUT_R2: + case EPD_LUT_R3: + adr = (bracket * 2080); + adr += (index - 0x21) * 260; + len = 260; + break; + case EPD_LUT_XON: + // XON LUT + adr = 23000 + (200 * bracket); + len = 200; + break; + } + + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(1); + delay_us(1000); + lutBuffer = malloc(len); + if (lutBuffer) spi_soft_read_buffer(0, adr, lutBuffer, len); + delay_us(1000); + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(0); + return lutBuffer; } -void display_send_start(uint8_t inverted) -{ - EPD_cmd(0); - if(inverted) - EPD_data(207); - else - EPD_data(203); - EPD_cmd(0x10); - epd_pin_enable(1); - GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); +void shiftRightByX(uint8_t *data, int X, int N) { + if (X < 0 || X >= 8) { + // Invalid shift value, X should be between 0 and 7 (inclusive) + return; + } + + // Perform the shift operation on each byte in the range + for (int i = 0; i < N; i++) { + data[i] = (data[i] >> X) | ((data[i + 1] & ((1 << X) - 1)) << (8 - X)); + } +} +void shiftLeftByX(uint8_t *data, int X, int N) { + if (X < 0 || X >= 8) { + // Invalid shift value, X should be between 0 and 7 (inclusive) + return; + } + + // Perform the shift operation on each byte in the range + for (int i = N - 1; i >= 0; i--) { + data[i] = (data[i] << X) | ((data[i - 1] >> (8 - X)) & ((1 << X) - 1)); + } +} +#define CHAR_WIDTH_BYTES 2 +#define CHAR_HEIGHT 20 +#define CHAR_WIDTH 12 +#define SCREEN_WIDTH 640 + +uint8_t buffer[CHAR_HEIGHT][640 / 8]; +uint8_t charbuffer[CHAR_HEIGHT][CHAR_WIDTH_BYTES + 1]; + +// uint16_t curX = 0; +#define CHAR_SPACING 1 +#define EMPTY_SPACING 3 + +uint16_t loadCharacter(uint8_t currentChar, uint16_t curX, bool first) { + + currentChar-=0x20; + + memset(charbuffer, 0, sizeof(charbuffer)); + for (uint8_t d = 0; d < CHAR_HEIGHT; d++) { + for (uint8_t c = 0; c < CHAR_WIDTH_BYTES; c++) { + charbuffer[d][c] = font[currentChar][c + (2 * d)]; + } + } + + // find amount of left whitespace and compensate + uint8_t leftShift = 0; + for (uint8_t left = 0; left < CHAR_WIDTH; left++) { + bool leftAdjusted = false; + for (uint8_t height = 0; height < CHAR_HEIGHT; height++) { + if (charbuffer[height][0] & 0x01) { + leftAdjusted = true; + break; + } + } + if (leftAdjusted) { + break; + } else { + for (uint8_t height = 0; height < CHAR_HEIGHT; height++) { + shiftRightByX(&(charbuffer[height][0]), 1, CHAR_WIDTH_BYTES); + } + leftShift++; + } + } + + // find width for character + uint8_t width = 0; + for (int8_t curBit = CHAR_WIDTH + 1; curBit > 0; curBit--) { + bool widthFound = false; + for (uint8_t height = 0; height < CHAR_HEIGHT; height++) { + if (charbuffer[height][curBit / 8] & (1 << (curBit % 8))) { + widthFound = true; + break; + } + } + if (widthFound) { + width = curBit + 1; + break; + } + } + + if (!first) { + curX += CHAR_SPACING; + } + + for (uint8_t height = 0; height < CHAR_HEIGHT; height++) { + shiftLeftByX(&(charbuffer[height][0]), curX % 8, CHAR_WIDTH_BYTES + 1); + } + + for (uint8_t d = 0; d < CHAR_HEIGHT; d++) { + for (uint8_t c = 0; c < CHAR_WIDTH_BYTES + 1; c++) { + buffer[d][(curX / 8) + c] |= charbuffer[d][c]; + } + } + if (width == 0) width = EMPTY_SPACING; + curX += width; + return curX; } -void display_send_stop() -{ - GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); - epd_pin_enable(0); +void dumpBuffer(uint16_t xloc, uint16_t yloc, uint16_t width) { + xloc = SCREEN_WIDTH - xloc; + + setDisplayWindow(xloc - width, yloc, xloc, yloc + CHAR_HEIGHT); + display_send_start(0); + for (uint8_t curY = 0; curY < CHAR_HEIGHT; curY++) { + for (uint16_t curX = 0; curX < width; curX += 8) { + interleaveColor(buffer[curY][curX / 8]); + } + } + display_send_stop(); } -void init_epd(void) -{ - init_GPIO_EPD(); - epd_reset(); - epd_reset(); - EPD_cmd(0x65); - EPD_data(1); - GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW); - spi_soft_send_byte(0xAB); - GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH); - EPD_cmd(0x65); - EPD_data(0); - delay(1000); - epd_send_init(); - delay(1000); - EPD_cmd(4); - BUSY_wait(0x32u); - epd_read_write_30(); +void loadLUTSfromEEPROM() { + uint8_t bracket = getTempBracket(); + for (uint8_t c = EPD_LUT_B; c <= EPD_LUT_R3; c++) { + struct epd_colorlut *colorlut = (struct epd_colorlut *)loadLUT(c, bracket); + for (uint8_t part = 0; part < 20; part++) { + if (colorlut->part[part].repeat) colorlut->part[part].repeat = 1; + } + lutBeginTX(c); + for (uint16_t d = 0; d < 260; d++) { + display_tx_byte(((uint8_t *)colorlut)[d]); + } + lutEndTX(); + if (colorlut) free(colorlut); + } + + struct epd_vcomlut *vcomlut = (struct epd_vcomlut *)loadLUT(EPD_LUT_VCOM, bracket); + for (uint8_t part = 0; part < 20; part++) { + if (vcomlut->part[part].repeat) vcomlut->part[part].repeat = 1; + } + lutBeginTX(EPD_LUT_VCOM); + for (uint16_t d = 0; d < 220; d++) { + display_tx_byte(((uint8_t *)vcomlut)[d]); + } + lutEndTX(); + if (vcomlut) free(vcomlut); + + struct epd_xonlut *xonlut = (struct epd_xonlut *)loadLUT(EPD_LUT_XON, bracket); + for (uint8_t part = 0; part < 20; part++) { + if (xonlut->part[part].repeat) xonlut->part[part].repeat = 1; + } + lutBeginTX(EPD_LUT_XON); + for (uint16_t d = 0; d < 200; d++) { + display_tx_byte(((uint8_t *)xonlut)[d]); + } + lutEndTX(); + if (xonlut) free(xonlut); } + +void init_GPIO_EPD() { + SSP_CFG_Type v0; + SPI_Param_Type spiParaStruct; + GPIO_PinMuxFun(EPD_MOSI, 0); + GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT); + GPIO_PinMuxFun(EPD_CLK, 0); + GPIO_SetPinDir(EPD_CLK, GPIO_OUTPUT); + GPIO_PinMuxFun(EPD_CS, 0); + GPIO_SetPinDir(EPD_CS, GPIO_OUTPUT); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); + GPIO_PinMuxFun(EPD_BUSY, 0); + GPIO_SetPinDir(EPD_BUSY, GPIO_INPUT); + GPIO_PinModeConfig(EPD_BUSY, PINMODE_PULLUP); + GPIO_PinMuxFun(EPD_RESET, 0); + GPIO_SetPinDir(EPD_RESET, GPIO_OUTPUT); + GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH); + GPIO_PinMuxFun(EPD_DC, 0); + GPIO_SetPinDir(EPD_DC, GPIO_OUTPUT); + GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH); + GPIO_PinMuxFun(EPD_BS, 0); + GPIO_SetPinDir(EPD_BS, GPIO_OUTPUT); + GPIO_WritePinOutput(EPD_BS, GPIO_IO_LOW); + GPIO_PinMuxFun(EPD_HLT_CTRL, 0); + GPIO_SetPinDir(EPD_HLT_CTRL, GPIO_OUTPUT); + GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH); + GPIO_PinMuxFun(EPD_MISO, 0); + GPIO_SetPinDir(EPD_MISO, GPIO_INPUT); + GPIO_PinModeConfig(EPD_MISO, PINMODE_DEFAULT); + memset(&v0, 0, 9); + v0.timeOutVal = 0; + SSP_Init(SSP2_ID, &v0); + spiParaStruct.spiClkPhase = SPI_SCPHA_1; + spiParaStruct.spiClkPolarity = SPI_SCPOL_LOW; + SPI_Config(SSP2_ID, &spiParaStruct); + CLK_I2SClkSrc(CLK_I2S_XTAL32M); + CLK_SSPClkSrc(CLK_SSP_ID_2, CLK_SSP_I2S); + CLK_I2SClkDivider(1, 1); +} + +void fillWindow(uint16_t x, uint16_t y, uint16_t xe, uint16_t ye, uint8_t color) { + setDisplayWindow(x, y, xe, ye); + display_send_start(0); + + for (uint32_t c = 0; c < (xe - x) * (ye - y) / 8; c++) { + interleaveColor(0x00); + } + + display_send_stop(); +} + +void epd_refresh_and_sleep() { + loadLUTSfromEEPROM(EPDtempBracket); + + // epdPrintf(50,100,false,"Blaat! Dit is een test %d", 6); + + EPD_cmd(EPD_REFRESH); + delay(100000); + do_sleeped_epd_refresh(); + init_GPIO_EPD(); + epd_reset(); + epd_reset(); + EPD_cmd(EPD_POWER_SETTING); + EPD_data(2); + EPD_data(0); + EPD_data(0); + EPD_data(0); + delay_us(500000); + EPD_cmd(EPD_POWER_OFF); + delay_us(1000000); + BUSY_wait(0x32u); + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(1); + GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW); + spi_soft_send_byte(EPD_EEPROM_SLEEP); + GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH); + EPD_cmd(EPD_SPI_FLASH_CONTROL); + EPD_data(0); + EPD_cmd(EPD_DEEP_SLEEP); + EPD_data(0xA5); +} + +void epd_pin_enable(int a1) { + if (a1) { + GPIO_PinMuxFun(EPD_CLK, GPIO22_SSP2_SCK); + GPIO_PinMuxFun(EPD_MOSI, GPIO12_SSP2_TXD); + GPIO_PinMuxFun(EPD_MISO, GPIO13_SSP2_RXD); + SSP_Enable(SSP2_ID); + } else { + SSP_Disable(SSP2_ID); + GPIO_PinMuxFun(EPD_MOSI, 0); + GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT); + GPIO_PinMuxFun(EPD_CLK, 0); + GPIO_SetPinDir(EPD_CLK, GPIO_OUTPUT); + GPIO_PinMuxFun(EPD_MISO, 0); + GPIO_SetPinDir(EPD_MISO, GPIO_INPUT); + GPIO_PinModeConfig(EPD_MISO, PINMODE_DEFAULT); + } +} + +void lutBeginTX(uint8_t reg) { + EPD_cmd(reg); + epd_pin_enable(1); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); +} + +void lutEndTX() { + GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); + epd_pin_enable(0); +} + +void setDisplayWindow(uint16_t x, uint16_t y, uint16_t xe, uint16_t ye) { + x &= 0xFFF8; // byte boundary + xe = (xe - 1) | 0x0007; // byte boundary - 1 + EPD_cmd(0x91); + epdWrite(0x90, 9, x / 256, x % 256, xe / 256, xe % 256, y / 256, y % 256, ye / 256, ye % 256, 0x01); +} + +void display_tx_byte(uint8_t data) { + SSP_SendData(SSP2_ID, data); +} + +void display_send_start(uint8_t inverted) { + EPD_cmd(EPD_START_DATA); + epd_pin_enable(1); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); +} + +void display_send_stop() { + for (int i = 0; i < 0xF; ++i) + __ISB(); + GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH); + epd_pin_enable(0); +} + +void init_epd(void) { + printf("EPD Powerup begin\n"); + init_GPIO_EPD(); + epd_reset(); + + EPD_cmd(EPD_POWER_ON); + BUSY_wait(0x32u); + + // wake the eeprom + epdWrite(EPD_SPI_FLASH_CONTROL, 1, 0x01); + GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW); + epdWrite(EPD_WAKE_EEPROM, 0x00); + GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH); + epdWrite(EPD_SPI_FLASH_CONTROL, 1, 0x00); + + epdWrite(EPD_POWER_SETTING, 4, 0x37, 0x00, 0x05, 0x05); // 0x37 - 00- 05 05 + epdWrite(EPD_PANEL_SETTING, 2, 0xC3, 0x88); // CB-88 // CB-08 // C3-reverse + + // epdWrite(EPD_UNKNOWN_1, 1, 0x03); + + epdWrite(EPD_POWER_OFF_SEQUENCE, 1, 0x00); + epdWrite(EPD_BOOSTER_SOFT_START, 0x03, 199, 204, 45); + + epdWrite(EPD_PLL_CONTROL, 0x01, 60); + epdWrite(EPD_TEMP_SELECT, 0x01, 0x00); + epdWrite(EPD_VCOM_DATA_INTERVAL, 0x01, 119); + epdWrite(EPD_TCON_SET, 0x01, 34); + epdWrite(EPD_TRES, 0x04, 2, 128, 1, 128); + + //setDisplayWindow(96, 32, 496, 332); + + EPDtempBracket = getTempBracket(); + loadFrameRatePLL(EPDtempBracket); + loadTempVCOMDC(EPDtempBracket); + printf("EPD Powerup complete\n"); +} + +void epdPrintf(uint16_t x, uint16_t y, bool color, const char *c, ...) { + // Render the text + char out_buffer[96]; + + uint16_t curX = 0; + memset(buffer, 0, sizeof(buffer)); + memset(charbuffer, 0, sizeof(charbuffer)); + va_list lst; + va_start(lst, c); + vsnprintf(out_buffer,256, c, lst); + va_end(lst); + + curX = x % 8; + + char *text = (char *)out_buffer; + memset(charbuffer, 0, sizeof(charbuffer)); + curX = loadCharacter(*text, curX, true); + text++; + + while (*text != '\0') { + memset(charbuffer, 0, sizeof(charbuffer)); + curX = loadCharacter(*text, curX, false); + text++; + } + + x /= 8; + x *= 8; + dumpBuffer(x, y, curX); +} \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.h index 5cebf061..9b68d899 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.h @@ -1,7 +1,8 @@ #pragma once -#include +//#include #include #include +#include #define DISPLAY_WIDTH (640) #define DISPLAY_HEIGHT (384) @@ -16,6 +17,18 @@ #define FORE_COLOR_2 4 #define FORE_COLOR_3 0 +#define EPD_LUT_DEFAULT 0 +#define EPD_LUT_NO_REPEATS 1 +#define EPD_LUT_FAST_NO_REDS 2 +#define EPD_LUT_FAST 3 + +#define EPD_DIRECTION_X false +#define EPD_DIRECTION_Y true +#define EPD_SIZE_SINGLE false +#define EPD_SIZE_DOUBLE true +#define EPD_COLOR_RED true +#define EPD_COLOR_BLACK false + void init_GPIO_EPD(); void display_send_buffer(); @@ -25,5 +38,16 @@ void display_tx_byte(uint8_t data); void display_send_start(uint8_t inverted); void display_send_stop(); +void setDisplayWindow(uint16_t x, uint16_t y, uint16_t xe, uint16_t ye); + void init_epd(); -void refresh_epd(); \ No newline at end of file +void refresh_epd(); + +void lutBeginTX(uint8_t reg); +void lutEndTX(); + +void epd_pin_enable(int a1); + + +void fillWindow(uint16_t x, uint16_t y, uint16_t xe, uint16_t ye, uint8_t color); +void epdPrintf(uint16_t x, uint16_t y, bool color, const char* c, ...); \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/gpio.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/gpio.c index 04da951c..8d1c19cb 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/gpio.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/gpio.c @@ -1,6 +1,6 @@ #include "nfc.h" -#include +//#include #include #include #include @@ -12,6 +12,8 @@ #include "mz100_pinmux.h" #include "mz100_gpio.h" #include "util.h" +#include "printf.h" + void NVIC_some_IRQ1(unsigned int a1) { diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.c old mode 100644 new mode 100755 index 2d83700d..41be818d --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.c @@ -1,38 +1,38 @@ -#include -#include -#include -#include -#include "core_cm3.h" #include "main.h" -#include "mz100_pinmux.h" -#include "mz100_gpio.h" -#include "mz100_uart.h" -#include "mz100_clock.h" -#include "mz100_sleep.h" -#include "mz100_flash.h" -#include "epd.h" -#include "mz100_ssp.h" -#include "mz100_pmu.h" -#include "core_cminstr.h" -#include "zigbee.h" -#include "util.h" -#include "settings.h" -#include "eeprom.h" -#include "proto.h" -#include "comms.h" -#include "chars.h" -#include "mz100.h" -#include "timer.h" -#include "util.h" -#include "ccm.h" -#include "nfc.h" -#include "gpio.h" -#include "compression.h" -#include "syncedproto.h" -#include "proto.h" -#include "powermgt.h" -#define SW_VER_CURRENT (0x0000011300000000ull) // top 16 bits are off limits, xxxx.VV.tt.vvvv.mmmm means version V.t.v.m +#include +#include +// #include +#include + +#include "ccm.h" +#include "chars.h" +#include "comms.h" +#include "core_cm3.h" +#include "eeprom.h" +#include "epd.h" +#include "gpio.h" +#include "mz100.h" +#include "mz100_aon_ram.h" +#include "mz100_clock.h" +#include "mz100_flash.h" +#include "mz100_gpio.h" +#include "mz100_pinmux.h" +#include "mz100_pmu.h" +#include "mz100_sleep.h" +#include "mz100_ssp.h" +#include "mz100_uart.h" +#include "powermgt.h" +#include "printf.h" +#include "proto.h" +#include "settings.h" +#include "syncedproto.h" +#include "timer.h" +#include "userinterface.h" +#include "util.h" +#include "zigbee.h" + +#define SW_VER_CURRENT (0x0000011300000000ull) // top 16 bits are off limits, xxxx.VV.tt.vvvv.mmmm means version V.t.v.m #define SW_DEFAULT_MAC (0x0000000000000014ull) uint64_t __attribute__((section(".ver"))) mCurVersionExport = SW_VER_CURRENT; @@ -40,21 +40,25 @@ uint64_t __attribute__((section(".default_mac"))) default_mac = SW_DEFAULT_MAC; char macStr[32]; char macStr1[32]; -uint8_t mSelfMac[8]; +// uint8_t mSelfMac[8]; -void prvApplyUpdateIfNeeded() -{ +#define TAG_MODE_CHANSEARCH 0 +#define TAG_MODE_ASSOCIATED 1 + +__attribute__((section(".aon"))) uint8_t currentTagMode = TAG_MODE_CHANSEARCH; +__attribute__((section(".aon"))) volatile struct zigbeeCalibDataStruct zigbeeCalibData; + +void prvApplyUpdateIfNeeded() { uint32_t ofst, now, size, pieceSz = 0x2000; uint8_t chunkStore[0x2000]; - (*(volatile unsigned int *)0x130000) = 0; // Invalidate RAM in any case so the next boot will be a full one + (*(volatile unsigned int *)0x130000) = 0; // Invalidate RAM in any case so the next boot will be a full one (*(volatile unsigned int *)0x130400) = 0; printf("Applying update\r\n"); qspiEraseRange(EEPROM_OS_START, EEPROM_OS_LEN); size = EEPROM_OS_LEN; - for (ofst = 0; ofst < size; ofst += now) - { + for (ofst = 0; ofst < size; ofst += now) { now = size - ofst; if (now > pieceSz) now = pieceSz; @@ -64,138 +68,38 @@ void prvApplyUpdateIfNeeded() WDT_RestartCounter(); } - printf("Erz IMAGES\r\n"); - qspiEraseRange(EEPROM_IMG_START, EEPROM_IMG_LEN); - printf("Erz update\r\n"); - qspiEraseRange(EEPROM_UPDATE_START, EEPROM_UPDATE_LEN); + // printf("Erz IMAGES\r\n"); + // qspiEraseRange(EEPROM_IMG_START, EEPROM_IMG_LEN); + // printf("Erz update\r\n"); + // qspiEraseRange(EEPROM_UPDATE_START, EEPROM_UPDATE_LEN); sleep_with_with_wakeup(1000); } -static const char *fwVerString(void) -{ - static char fwVer[64] = {}; - sprintf(fwVer, "FW v%u.%u.%u.%u Batt: %imV Temp: %iC", - (uint8_t)(mCurVersionExport >> 40), - (uint8_t)(mCurVersionExport >> 32), - (uint16_t)(mCurVersionExport >> 16), - (uint16_t)(mCurVersionExport), - measureBattery(), - measureTemp()); - - return fwVer; -} - -uint8_t mScreenRow[DISPLAY_WIDTH / 2]; -void uiPrvFullscreenMsg(const char *str, const char *line2, const char *line3) -{ - struct CharDrawingParams cdp; - uint16_t i, r, textRow, textRowEnd; - static const char zero = 0; - uint8_t rowIdx; - const char *strA[] = {str ? str : "", line2 ? line2 : "", line3 ? line3 : ""}; - - printf("MESSAGE: '%s', '%s', '%s'\r\n", strA[0], strA[1], strA[2]); - - if (NO_GUI == 1) - return; // Make everything faster for debugging.!!!! - init_epd(); - display_send_start(false); - - rowIdx = 0; - - cdp.magnify = MAGNIFY1; - cdp.str = strA[0]; - cdp.x = 1; - - cdp.foreColor = FORE_COLOR_1; - cdp.backColor = BACK_COLOR; - textRow = 10; - - textRowEnd = textRow + CHAR_HEIGHT * cdp.magnify; - for (r = 0; r < DISPLAY_HEIGHT; r++) - { - - // clear the row - for (i = 0; i < sizeof(mScreenRow); i++) - mScreenRow[i] = 0x33; - - if (r >= textRowEnd) - { - - switch (rowIdx) - { - case 0: - rowIdx = 1; - - textRow = textRowEnd + 20; - cdp.magnify = MAGNIFY2; - cdp.foreColor = FORE_COLOR_2; - cdp.str = strA[1]; - cdp.x = 1; - textRowEnd = textRow + CHAR_HEIGHT * cdp.magnify; - break; - - case 1: - rowIdx = 2; - - textRow = DISPLAY_HEIGHT - CHAR_HEIGHT; - cdp.magnify = MAGNIFY3; - cdp.foreColor = FORE_COLOR_3; - cdp.str = strA[2]; - cdp.x = 1; - textRowEnd = textRow + CHAR_HEIGHT; - break; - - case 2: - cdp.str = (const char *)&zero; - break; - } - } - else if (r > textRow) - { - cdp.imgRow = r - textRow; - charsDrawString(&cdp); - } - - for (i = 0; i < sizeof(mScreenRow); i++) - display_tx_byte(mScreenRow[i]); - } - WDT_RestartCounter(); - - display_send_stop(); - epd_refresh_and_sleep(); -} - -void prvEepromIndex(struct EepromContentsInfo *eci) -{ +void prvEepromIndex(struct EepromContentsInfo *eci) { struct EepromImageHeader eih; uint32_t addr; - for (addr = EEPROM_IMG_START; addr - EEPROM_IMG_START < EEPROM_IMG_LEN; addr += EEPROM_IMG_EACH) - { - + for (addr = EEPROM_IMG_START; addr - EEPROM_IMG_START < EEPROM_IMG_LEN; addr += EEPROM_IMG_EACH) { uint32_t *addrP, *szP = NULL; uint64_t *verP = NULL; FLASH_Read(0, addr, (uint8_t *)&eih, sizeof(struct EepromImageHeader)); printf("DATA slot 0x%06x: type 0x%08x ver 0x%08x%08x\r\n", addr, eih.validMarker, (uint32_t)(eih.version >> 32), (uint32_t)eih.version); - switch (eih.validMarker) - { - case EEPROM_IMG_INPROGRESS: - verP = &eci->latestInprogressImgVer; - addrP = &eci->latestInprogressImgAddr; - break; + switch (eih.validMarker) { + case EEPROM_IMG_INPROGRESS: + verP = &eci->latestInprogressImgVer; + addrP = &eci->latestInprogressImgAddr; + break; - case EEPROM_IMG_VALID: - verP = &eci->latestCompleteImgVer; - addrP = &eci->latestCompleteImgAddr; - szP = &eci->latestCompleteImgSize; - break; + case EEPROM_IMG_VALID: + verP = &eci->latestCompleteImgVer; + addrP = &eci->latestCompleteImgAddr; + szP = &eci->latestCompleteImgSize; + break; } - if (verP && eih.version >= *verP) - { + if (verP && eih.version >= *verP) { *verP = eih.version; *addrP = addr; if (szP) @@ -203,10 +107,9 @@ void prvEepromIndex(struct EepromContentsInfo *eci) } } } -void prvWriteNewHeader(struct EepromImageHeaderOld *eih, uint32_t addr, uint32_t eeSize, uint64_t ver, uint32_t size) -{ +void prvWriteNewHeader(struct EepromImageHeaderOld *eih, uint32_t addr, uint32_t eeSize, uint64_t ver, uint32_t size) { qspiEraseRange(addr, eeSize); - bzero(eih, sizeof(struct EepromImageHeaderOld)); + // bzero(eih, sizeof(struct EepromImageHeaderOld)); eih->version = ver; eih->validMarker = EEPROM_IMG_INPROGRESS; eih->size = size; @@ -214,26 +117,10 @@ void prvWriteNewHeader(struct EepromImageHeaderOld *eih, uint32_t addr, uint32_t FLASH_Write(false, addr, (uint8_t *)eih, sizeof(struct EepromImageHeaderOld)); } -static void uiPrvDrawImageAtAddress(uint32_t addr, uint32_t size) -{ - printf("Drawing image now\r\n"); - if (size < 6) // we need enough size to even sort out what this is, that needs 6 bytes - return; - - // uiPrvDrawBitmap(addr + sizeof(struct EepromImageHeader), size); -} -void uiPrvDrawLatestImage(const struct EepromContentsInfo *eci) -{ - if (eci->latestCompleteImgAddr) - uiPrvDrawImageAtAddress(eci->latestCompleteImgAddr, eci->latestCompleteImgSize); -} - -static void prvGetSelfMac(void) -{ +static void prvGetSelfMac(void) { FLASH_Read(0, EEPROM_MAC_INFO_START, mSelfMac, 8); - if ((((uint32_t *)mSelfMac)[0] | ((uint32_t *)mSelfMac)[1]) == 0 || (((uint32_t *)mSelfMac)[0] & ((uint32_t *)mSelfMac)[1]) == 0xffffffff) - { // fastest way to check for all ones or all zeroes + if ((((uint32_t *)mSelfMac)[0] | ((uint32_t *)mSelfMac)[1]) == 0 || (((uint32_t *)mSelfMac)[0] & ((uint32_t *)mSelfMac)[1]) == 0xffffffff) { // fastest way to check for all ones or all zeroes printf("mac unknown\r\n"); // Write a blank mac to have something to work with. @@ -243,35 +130,14 @@ static void prvGetSelfMac(void) } } -static void showVersionAndVerifyMatch(void) -{ - // the &mCurVersionExport access is necessary to make sure mCurVersionExport is referenced - /* printf("Booting FW ver 0x%08x%08x (at 0x%08x)\r\n", - (unsigned)(mCurVersionExport >> 32), (unsigned)mCurVersionExport, &mCurVersionExport); - if (((uint32_t)&mCurVersionExport) - 0x100000 != HW_TYPE_74_INCH_BWR_ROM_VER_OFST - 0x20) - { - printf("ver loc mismatch\r\n"); - sleep_with_with_wakeup(0); - } - if (mCurVersionExport & ~VERSION_SIGNIFICANT_MASK) - { - printf("ver num @ red zone\r\n"); - sleep_with_with_wakeup(0); - }*/ -} - -uint8_t showChannelSelect() -{ // returns 0 if no accesspoints were found +uint8_t showChannelSelect() { // returns 0 if no accesspoints were found uint8_t result[sizeof(channelList)]; memset(result, 0, sizeof(result)); powerUp(INIT_RADIO); // uiPrvFullscreenMsg("Scanning", NULL, NULL); - for (uint8_t i = 0; i < 4; i++) - { - for (uint8_t c = 0; c < sizeof(channelList); c++) - { - if (detectAP(channelList[c])) - { + for (uint8_t i = 0; i < 4; i++) { + for (uint8_t c = 0; c < sizeof(channelList); c++) { + if (detectAP(channelList[c])) { if (mLastLqi > result[c]) result[c] = mLastLqi; printf("Channel: %d - LQI: %d RSSI %d\n", channelList[c], mLastLqi, mLastRSSI); @@ -281,10 +147,8 @@ uint8_t showChannelSelect() uint8_t highestLqi = 0; uint8_t highestSlot = 0; - for (uint8_t c = 0; c < sizeof(result); c++) - { - if (result[c] > highestLqi) - { + for (uint8_t c = 0; c < sizeof(result); c++) { + if (result[c] > highestLqi) { highestSlot = channelList[c]; highestLqi = result[c]; } @@ -293,17 +157,13 @@ uint8_t showChannelSelect() return highestSlot; } -uint8_t channelSelect() -{ // returns 0 if no accesspoints were found +uint8_t channelSelect() { // returns 0 if no accesspoints were found uint8_t result[16]; memset(result, 0, sizeof(result)); - for (uint8_t i = 0; i < 2; i++) - { - for (uint8_t c = 0; c < sizeof(channelList); c++) - { - if (detectAP(channelList[c])) - { + for (uint8_t i = 0; i < 2; i++) { + for (uint8_t c = 0; c < sizeof(channelList); c++) { + if (detectAP(channelList[c])) { if (mLastLqi > result[c]) result[c] = mLastLqi; } @@ -312,10 +172,8 @@ uint8_t channelSelect() uint8_t highestLqi = 0; uint8_t highestSlot = 0; - for (uint8_t c = 0; c < sizeof(result); c++) - { - if (result[c] > highestLqi) - { + for (uint8_t c = 0; c < sizeof(result); c++) { + if (result[c] > highestLqi) { highestSlot = channelList[c]; highestLqi = result[c]; } @@ -325,139 +183,51 @@ uint8_t channelSelect() return highestSlot; } -void __attribute__((interrupt)) NMIException(void) -{ +void __attribute__((interrupt)) NMIException(void) { printf("-----------> NMIException\r\n"); PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; PMU->PWR_MODE.BF.PWR_MODE = 0; NVIC_SystemReset(); } -void __attribute__((interrupt)) HardFaultException(void) -{ +void __attribute__((interrupt)) HardFaultException(void) { printf("-----------> HardFaultException\r\n"); PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; PMU->PWR_MODE.BF.PWR_MODE = 0; NVIC_SystemReset(); } -void __attribute__((interrupt)) MemManageException(void) -{ +void __attribute__((interrupt)) MemManageException(void) { printf("-----------> MemManageException\r\n"); PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; PMU->PWR_MODE.BF.PWR_MODE = 0; NVIC_SystemReset(); } -void __attribute__((interrupt)) BusFaultException(void) -{ +void __attribute__((interrupt)) BusFaultException(void) { printf("-----------> BusFaultException\r\n"); PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; PMU->PWR_MODE.BF.PWR_MODE = 0; NVIC_SystemReset(); } -void __attribute__((interrupt)) UsageFaultException(void) -{ +void __attribute__((interrupt)) UsageFaultException(void) { printf("-----------> UsageFaultException\r\n"); PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; PMU->PWR_MODE.BF.PWR_MODE = 0; NVIC_SystemReset(); } -void __attribute__((interrupt)) SVCHandler(void) -{ +void __attribute__((interrupt)) SVCHandler(void) { } -void __attribute__((interrupt)) DebugMonitor(void) -{ +void __attribute__((interrupt)) DebugMonitor(void) { } -void __attribute__((interrupt)) PendSVC(void) -{ +void __attribute__((interrupt)) PendSVC(void) { } -extern struct blockRequest curBlock; // used by the block-requester, contains the next request that we'll send -extern struct AvailDataInfo curDataInfo; // last 'AvailDataInfo' we received from the AP -extern bool requestPartialBlock; // if we should ask the AP to get this block from the host or not -int main(void) -{ - uint8_t currentChannel = 0; - struct Settings settings; - uint32_t sleepDuration = 5000; - struct CommsInfo ci; - uint32_t reset_reason = PMU_GetLastResetCause(); - uint8_t pwr_mode_at_boot = PMU->PWR_MODE.BF.PWR_MODE; - - (*(volatile unsigned int *)0x20124000) = 0x100004; // On WARM RESET: Goto this address. -> entry - (*(volatile unsigned int *)0xE000ED08) = 0x20100000; // Vector table in RAM and offset 0x4000 - (*(volatile unsigned int *)0xE000E41A) = 0x40; - - CLK_SystemClkInit(CLK_SYS_XTAL64M, CLK_SYS_64M); - CLK_Xtal32MEnable(CLK_OSC_INTERN); - while (CLK_GetClkStatus(CLK_OUT_XTAL64M) != 1) - ; - - // UART 1 DEBUG OUT - GPIO_PinModeConfig(UART_TX, PINMODE_DEFAULT); - GPIO_PinModeConfig(UART_RX, PINMODE_DEFAULT); - GPIO_PinMuxFun(UART_TX, GPIO4_UART2_TXD); // UART - GPIO_PinMuxFun(UART_RX, GPIO6_UART2_RXD); // UART - UART_CFG_Type uartcfg; - uartcfg.baudRate = 115200; - uartcfg.dataBits = UART_DATABITS_8; - uartcfg.stopBits = 1; - uartcfg.parity = UART_PARITY_NONE; - uartcfg.autoFlowControl = DISABLE; - UART_Init(1, &uartcfg); - - UART_FIFO_Type uartFifo; - uartFifo.FIFO_ResetRx = 1; - uartFifo.FIFO_ResetTx = 1; - uartFifo.FIFO_Function = 1; - uartFifo.FIFO_RcvrTrigger = 2; - uartFifo.FIFO_TxEmptyTrigger = 3; - UART_FIFOConfig(1, &uartFifo); - // UART 1 DEBUG OUT - - if (!(~(*(volatile unsigned int *)0x4A080000) << 30)) - { - NVIC_EnableIRQ(ExtPin5_IRQn); - NVIC_EnableIRQ(RTC_IRQn); - } - - (*(volatile unsigned int *)0x4A070004) = ((*(volatile unsigned int *)0x4A070004) & 0xFFFFFFE0) + 2; - PMU->PWR_MODE.BF.PWR_MODE = 2; - uint32_t v0 = FLASH_WordRead(FLASH_NORMAL_READ, 4u); - char v1; - if (!(~v0 << 25)) - { - CLK_RC32MEnable(); - while (CLK_GetClkStatus(CLK_OUT_RC32M) != 1) - ; - v1 = CLK_RC32MCalibration(CLK_AUTO_CAL, 0); - FLASH_WordWrite(FLASH_PROGRAM_NORMAL, 4u, (v0 & 0xFFFFFF00) | (v1 & 0x7F)); - } - - //** WATCHDOG - CLK_ModuleClkEnable(CLK_WDT); - WDT_SetMode(WDT_MODE_RESET); - WDT_SetResetPulseLen(WDT_RESET_PULSE_LEN_256); - WDT_SetTimeoutVal(30); - WDT_RestartCounter(); - WDT_Enable(); - //** WATCHDOG - - //** GPIOS - init_GPIO_boot(); - // NFC POWER Should be on if NFC is wanted to be used - GPIO_PinOutputModeConfig(NFC_POWER, PIN_OUTPUT_MODE_NORMAL_FUNCTION); - GPIO_PinModeConfig(NFC_POWER, PINMODE_DEFAULT); - GPIO_PinMuxFun(NFC_POWER, 0); - GPIO_SetPinDir(NFC_POWER, GPIO_OUTPUT); - GPIO_WritePinOutput(NFC_POWER, 1); // Better power NFC up so IRQ will work unpowered later - //** GPIOS - //** RTC +void setupRTC() { CLK_Xtal32MEnable(CLK_OSC_INTERN); while (!CLK_GetClkStatus(CLK_OUT_XTAL64M)) ; @@ -480,277 +250,287 @@ int main(void) NVIC_ClearPendingIRQ(RTC_IRQn); RTC_IntMask(RTC_INT_CNT_UPP, UNMASK); NVIC_EnableIRQ(RTC_IRQn); - //*** RTC +} - //** Get the real wakeup reason - printf("Rst reason: %i\r\n", reset_reason); - uint32_t real_reason = 0; - if ((*(volatile unsigned int *)0x130400) != 0x11223344) - { - (*(volatile unsigned int *)0x130400) = 0x11223344; - currentChannel = 0; - (*(volatile unsigned int *)0x130404) = currentChannel; +void setupUART() { + // UART 1 DEBUG OUT + GPIO_PinModeConfig(UART_TX, PINMODE_DEFAULT); + GPIO_PinModeConfig(UART_RX, PINMODE_DEFAULT); + GPIO_PinMuxFun(UART_TX, GPIO4_UART2_TXD); // UART + GPIO_PinMuxFun(UART_RX, GPIO6_UART2_RXD); // UART + UART_CFG_Type uartcfg; + uartcfg.baudRate = 115200; + uartcfg.dataBits = UART_DATABITS_8; + uartcfg.stopBits = 1; + uartcfg.parity = UART_PARITY_NONE; + uartcfg.autoFlowControl = DISABLE; + UART_Init(1, &uartcfg); - nfc_i2c_init(); // This is only needed on a complete reboot + UART_FIFO_Type uartFifo; + uartFifo.FIFO_ResetRx = 1; + uartFifo.FIFO_ResetTx = 1; + uartFifo.FIFO_Function = 1; + uartFifo.FIFO_RcvrTrigger = 2; + uartFifo.FIFO_TxEmptyTrigger = 3; + UART_FIFOConfig(1, &uartFifo); + // UART 1 DEBUG OUT +} - if (reset_reason == 5) - { - if (pwr_mode_at_boot) - { - real_reason = 1; // POR Reset - } - else - { - real_reason = 3; // WDT Reset - } - } - else - { - if (reset_reason != 4) - { - if (real_reason == 1 && !pwr_mode_at_boot) - { - real_reason = 2; // System Reset - } - else - { - real_reason = 1; // POR Reset - } - } - else if (pwr_mode_at_boot != 1) - { - real_reason = 1; // POR Reset - } - } - } - else - { - currentChannel = (*(volatile unsigned int *)0x130404); - memcpy((uint8_t *)&curBlock, (uint8_t *)&(*(volatile unsigned int *)0x130500), sizeof(struct blockRequest)); - memcpy((uint8_t *)&curDataInfo, (uint8_t *)&(*(volatile unsigned int *)0x130600), sizeof(struct AvailDataInfo)); - memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES); - requestPartialBlock = false; - } - - showVersionAndVerifyMatch(); - timerInit(); +void setupWDT() { + //** WATCHDOG + CLK_ModuleClkEnable(CLK_WDT); + WDT_SetMode(WDT_MODE_RESET); + WDT_SetResetPulseLen(WDT_RESET_PULSE_LEN_256); + WDT_SetTimeoutVal(30); WDT_RestartCounter(); - prvGetSelfMac(); - initializeProto(); + WDT_Enable(); + //** WATCHDOG +} - printf("Booot OpenEPaperLink\r\n"); - if (real_reason == 1) - { +void setupGPIO() { + //** GPIOS + init_GPIO_boot(); + // NFC POWER Should be on if NFC is wanted to be used + GPIO_PinOutputModeConfig(NFC_POWER, PIN_OUTPUT_MODE_NORMAL_FUNCTION); + GPIO_PinModeConfig(NFC_POWER, PINMODE_DEFAULT); + GPIO_PinMuxFun(NFC_POWER, 0); + GPIO_SetPinDir(NFC_POWER, GPIO_OUTPUT); + GPIO_WritePinOutput(NFC_POWER, 1); // Better power NFC up so IRQ will work unpowered later + //** GPIOS + if (!(~(*(volatile unsigned int *)0x4A080000) << 30)) { + NVIC_EnableIRQ(ExtPin5_IRQn); + NVIC_EnableIRQ(RTC_IRQn); + } +} + +void setupCLKCalib() { + (*(volatile unsigned int *)0x4A070004) = ((*(volatile unsigned int *)0x4A070004) & 0xFFFFFFE0) + 2; + PMU->PWR_MODE.BF.PWR_MODE = 2; + uint32_t v0 = FLASH_WordRead(FLASH_NORMAL_READ, 4u); + char v1; + if (!(~v0 << 25)) { + CLK_RC32MEnable(); + while (CLK_GetClkStatus(CLK_OUT_RC32M) != 1) + ; + v1 = CLK_RC32MCalibration(CLK_AUTO_CAL, 0); + FLASH_WordWrite(FLASH_PROGRAM_NORMAL, 4u, (v0 & 0xFFFFFF00) | (v1 & 0x7F)); + } +} + +void TagAssociated() { + // associated + struct AvailDataInfo *avail; + // Is there any reason why we should do a long (full) get data request (including reason, status)? + if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || wakeUpReason != WAKEUP_REASON_TIMED) { + // check if we should do a voltage measurement (those are pretty expensive) + if (voltageCheckCounter == VOLTAGE_CHECK_INTERVAL) { + doVoltageReading(); + voltageCheckCounter = 0; + } else { + powerUp(INIT_TEMPREADING); + } + voltageCheckCounter++; + + // check if the battery level is below minimum, and force a redraw of the screen + + if ((lowBattery && !lowBatteryShown && tagSettings.enableLowBatSymbol) || (noAPShown && tagSettings.enableNoRFSymbol)) { + printf("For some reason, we're going to redraw the image. lowbat=%d, lowbatshown=%d, noAPShown=%d\n", lowBattery, lowBatteryShown, noAPShown); + // Check if we were already displaying an image + /* + if (curImgSlot != 0xFF) { + powerUp(INIT_EEPROM | INIT_EPD); + wdt60s(); + drawImageFromEeprom(curImgSlot); + powerDown(INIT_EEPROM | INIT_EPD); + } else { + powerUp(INIT_EPD); + showAPFound(); + powerDown(INIT_EPD); + } + */ + } + + powerUp(INIT_RADIO); + avail = getAvailDataInfo(); + powerDown(INIT_RADIO); + + if (avail != NULL) { + // we got some data! + longDataReqCounter = 0; + // since we've had succesful contact, and communicated the wakeup reason succesfully, we can now reset to the 'normal' status + wakeUpReason = WAKEUP_REASON_TIMED; + } + if (tagSettings.enableTagRoaming) { + uint8_t roamChannel = channelSelect(); + if (roamChannel) currentChannel = roamChannel; + } + } else { + powerUp(INIT_RADIO); + avail = getShortAvailDataInfo(); + powerDown(INIT_RADIO); + } + + addAverageValue(); + + if (avail == NULL) { + // no data :( this means no reply from AP + nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period + } else { + nextCheckInFromAP = avail->nextCheckIn; + // got some data from the AP! + if (avail->dataType != DATATYPE_NOUPDATE) { + // data transfer + if (processAvailDataInfo(avail)) { + // succesful transfer, next wake time is determined by the NextCheckin; + } else { + // failed transfer, let the algorithm determine next sleep interval (not the AP) + nextCheckInFromAP = 0; + } + } else { + // no data transfer, just sleep. + } + } + + uint16_t nextCheckin = getNextSleep(); + longDataReqCounter += nextCheckin; + + if (nextCheckin == INTERVAL_AT_MAX_ATTEMPTS) { + // We've averaged up to the maximum interval, this means the tag hasn't been in contact with an AP for some time. + if (tagSettings.enableScanForAPAfterTimeout) { + currentTagMode = TAG_MODE_CHANSEARCH; + return; + } + } + + // if the AP told us to sleep for a specific period, do so. + if (nextCheckInFromAP) { + sleep_with_with_wakeup(nextCheckInFromAP * 60000UL); + } else { + sleep_with_with_wakeup(getNextSleep() * 1000UL); + } +} + +void TagChanSearch() { + // not associated + if (((scanAttempts != 0) && (scanAttempts % VOLTAGEREADING_DURING_SCAN_INTERVAL == 0)) || (scanAttempts > (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS))) { + doVoltageReading(); + } + + // try to find a working channel + currentChannel = channelSelect(); + + // Check if we should redraw the screen with icons, info screen or screensaver + if ((!currentChannel && !noAPShown && tagSettings.enableNoRFSymbol) || + (lowBattery && !lowBatteryShown && tagSettings.enableLowBatSymbol) || + (scanAttempts == (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) { + powerUp(INIT_EPD); + wdt60s(); + if (curImgSlot != 0xFF) { + powerUp(INIT_EEPROM); + drawImageFromEeprom(curImgSlot); + powerDown(INIT_EEPROM); + } else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) { + showLongTermSleep(); + } else { + showNoAP(); + } + powerDown(INIT_EPD); + } + + // did we find a working channel? + if (currentChannel) { + // now associated! set up and bail out of this loop. + scanAttempts = 0; + wakeUpReason = WAKEUP_REASON_NETWORK_SCAN; + initPowerSaving(INTERVAL_BASE); + doSleep(getNextSleep() * 1000UL); + currentTagMode = TAG_MODE_ASSOCIATED; + return; + } else { + // still not associated + doSleep(getNextScanSleep(true) * 1000UL); + } +} + +int main(void) { + (*(volatile unsigned int *)0x20124000) = 0x100004; // On WARM RESET: Goto this address. -> entry + (*(volatile unsigned int *)0xE000ED08) = 0x20100000; // Vector table in RAM and offset 0x4000 + (*(volatile unsigned int *)0xE000E41A) = 0x40; // ?? + + timerInit(); + + CLK_SystemClkInit(CLK_SYS_XTAL64M, CLK_SYS_64M); + CLK_Xtal32MEnable(CLK_OSC_INTERN); + while (CLK_GetClkStatus(CLK_OUT_XTAL64M) != 1) + ; + + if (!loadValidateAonRam() || PMU_GetLastResetCause()) { + setupWDT(); + setupGPIO(); + setupCLKCalib(); + setupUART(); + printf("Rst reason: %i\r\n", PMU_GetLastResetCause()); + printf("AON is not valid!\n"); + setupRTC(); + clearAonRam(); + currentChannel = 0; + zigbeeCalibData.isValid = false; + wakeUpReason = WAKEUP_REASON_FIRSTBOOT; + prvGetSelfMac(); + initializeProto(); printf("Erz data\r\n"); + initPowerSaving(INTERVAL_BASE); + loadDefaultSettings(); + doVoltageReading(); + qspiEraseRange(EEPROM_IMG_START, EEPROM_IMG_LEN); qspiEraseRange(EEPROM_UPDATE_START, EEPROM_UPDATE_LEN); qspiEraseRange(EEPROM_SETTINGS_AREA_START, EEPROM_SETTINGS_AREA_LEN); sprintf(macStr, "(" MACFMT ")", MACCVT(mSelfMac)); - // uiPrvFullscreenMsg("HELLO OTA", macStr, fwVerString()); currentChannel = showChannelSelect(); - (*(volatile unsigned int *)0x130404) = currentChannel; - WDT_RestartCounter(); - - if (currentChannel) - { + if (currentChannel) { printf("AP Found\r\n"); + showAPFound(); sprintf(macStr1, "OpenEPaperLink Ch: %i", currentChannel); - uiPrvFullscreenMsg("AP Found", macStr1, macStr); timerDelay(TIMER_TICKS_PER_MSEC * 1000); - } - else - { + currentTagMode = TAG_MODE_ASSOCIATED; + } else { printf("No AP found\r\n"); - uiPrvFullscreenMsg("No AP Found", "OpenEPaperLink", macStr); sleep_with_with_wakeup(120000UL); + currentTagMode = TAG_MODE_CHANSEARCH; } + + } else { + // setupWDT(); + setupGPIO(); + // setupCLKCalib(); + // setupUART(); + // setupRTC(); + memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES); } - if (nfc_handle()) // If an image was uploaded via NFC lets display it. - { - struct EepromContentsInfo eci; - memset(&eci, 0x00, sizeof(eci)); - prvEepromIndex(&eci); - uiPrvDrawLatestImage(&eci); - sleep_with_with_wakeup(30 * 1000); - } - - while (1 == 1) - { + while (1) { + powerUp(INIT_UART); wdt10s(); - if (currentChannel) - { - // associated - - struct AvailDataInfo *avail; - // Is there any reason why we should do a long (full) get data request (including reason, status)? - if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || wakeUpReason != WAKEUP_REASON_TIMED) - { - // check if we should do a voltage measurement (those are pretty expensive) - /*if (voltageCheckCounter == VOLTAGE_CHECK_INTERVAL) - { - powerUp(INIT_RADIO); // load down the battery using the radio to get a good reading - powerUp(INIT_TEMPREADING | INIT_EPD_VOLTREADING); - powerDown(INIT_RADIO); - voltageCheckCounter = 0; - } - else - { - powerUp(INIT_TEMPREADING); - } - voltageCheckCounter++;*/ - - // check if the battery level is below minimum, and force a redraw of the screen - /*if ((lowBattery && !lowBatteryShown) || (noAPShown)) - { - // Check if we were already displaying an image - if (curImgSlot != 0xFF) - { - powerUp(INIT_EEPROM | INIT_EPD); - wdt60s(); - drawImageFromEeprom(curImgSlot); - powerDown(INIT_EEPROM | INIT_EPD); - } - else - { - powerUp(INIT_EPD); - showAPFound(); - powerDown(INIT_EPD); - } - }*/ - powerUp(INIT_RADIO); - avail = getAvailDataInfo(); - powerDown(INIT_RADIO); - - if (avail != NULL) - { - // we got some data! - longDataReqCounter = 0; - // since we've had succesful contact, and communicated the wakeup reason succesfully, we can now reset to the 'normal' status - wakeUpReason = WAKEUP_REASON_TIMED; - } - } - else - { - powerUp(INIT_RADIO); - avail = getShortAvailDataInfo(); - powerDown(INIT_RADIO); - } - - addAverageValue(); - - if (avail == NULL) - { - // no data :( - sleep_with_with_wakeup(60 * 1000UL); - nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period - } - else - { - nextCheckInFromAP = avail->nextCheckIn; - // got some data from the AP! - if (avail->dataType != DATATYPE_NOUPDATE) - { - // data transfer - if (processAvailDataInfo(avail)) - { - // succesful transfer, next wake time is determined by the NextCheckin; - } - else - { - // failed transfer, let the algorithm determine next sleep interval (not the AP) - nextCheckInFromAP = 0; - } - } - else - { - // no data transfer, just sleep. - } - } - - uint16_t nextCheckin = getNextSleep(); - longDataReqCounter += nextCheckin; - if (nextCheckin == INTERVAL_AT_MAX_ATTEMPTS) - { - // disconnected, obviously... - currentChannel = 0; - (*(volatile unsigned int *)0x130404) = currentChannel; - } - - // if the AP told us to sleep for a specific period, do so. - if (nextCheckInFromAP) - { - sleep_with_with_wakeup(nextCheckInFromAP * 60000UL); - } - else - { - sleep_with_with_wakeup(getNextSleep() * 1000UL); - } - } - else - { - // not associated - if (((scanAttempts != 0) && (scanAttempts % VOLTAGEREADING_DURING_SCAN_INTERVAL == 0)) || (scanAttempts > (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS))) - { - powerUp(INIT_RADIO); // load down the battery using the radio to get a good reading - powerUp(INIT_EPD_VOLTREADING); - powerDown(INIT_RADIO); - } - // try to find a working channel - powerUp(INIT_RADIO); - currentChannel = channelSelect(); - (*(volatile unsigned int *)0x130404) = currentChannel; - powerDown(INIT_RADIO); - - /*if ((!currentChannel && !noAPShown) || (lowBattery && !lowBatteryShown) || (scanAttempts == (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) - { - powerUp(INIT_EPD); - wdt60s(); - if (curImgSlot != 0xFF) - { - powerUp(INIT_EEPROM); - drawImageFromEeprom(curImgSlot); - powerDown(INIT_EEPROM); - } - else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) - { - showLongTermSleep(); - } - else - { - showNoAP(); - } - powerDown(INIT_EPD); - }*/ - - // did we find a working channel? - if (currentChannel) - { - // now associated! - scanAttempts = 0; - wakeUpReason = WAKEUP_REASON_NETWORK_SCAN; - initPowerSaving(INTERVAL_BASE); - sleep_with_with_wakeup(getNextSleep() * 1000UL); - } - else - { - // still not associated - //sleep_with_with_wakeup(getNextScanSleep(true) * 1000UL); - sleep_with_with_wakeup(10 * 60 * 1000UL); - } + switch (currentTagMode) { + case TAG_MODE_ASSOCIATED: + TagAssociated(); + break; + case TAG_MODE_CHANSEARCH: + TagChanSearch(); + break; } } - printf("sleep: %u\r\n", sleepDuration); - if (sleepDuration == 0) - sleepDuration = 60 * 1000 * 15; // never sleep forever! - sleep_with_with_wakeup(sleepDuration); return 0; } -int _write(int file, char *ptr, int len) -{ +int _write(int file, char *ptr, int len) { UART_SendBytes(1, ptr, len); return len; +} + +void _putchar(char c) { + _write(0, &c, 1); } \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h index 6aa0b408..ab44cabd 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h @@ -1,5 +1,5 @@ #pragma once -#include +//#include #include #include #include diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100.ld b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100.ld index 6139bc9a..bfbcf36c 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100.ld +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100.ld @@ -4,8 +4,9 @@ GROUP(-lgcc -lc -lnosys) MEMORY { FLASH (rx) : ORIGIN = 0x100000, LENGTH = 80k - RAM (rwx) : ORIGIN = 0x20100000 + 80k, LENGTH = 160k - 80k - 16k - RAM1 (rwx) : ORIGIN = 0x20124000 , LENGTH = 16k + RAM (rwx) : ORIGIN = 0x20100000 + 80k, LENGTH = 160k - 80k - 2k + AONSHADOW (rwx) : ORIGIN = 0x20128000 - 2k, LENGTH = 2k + AON (rwx) : ORIGIN = 0x20130000 , LENGTH = 4k } ENTRY(Reset_Handler) @@ -123,6 +124,27 @@ SECTIONS /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + +.aon (NOLOAD): + { + . = ALIGN(4); + _start_of_aon = .; + *(.aon) + *(.aon.*) + . = ALIGN(4); + _end_of_aon = .; + + } > AON +.aonshadow (NOLOAD): + { + . = ALIGN(4); + _start_of_aonshadow = .; + *(.aonshadow) + *(.aonshadow.*) + . = ALIGN(4); + _end_of_aonshadow = .; + + } > AONSHADOW } diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.c new file mode 100644 index 00000000..bdd147ff --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.c @@ -0,0 +1,43 @@ +#include "mz100_aon_ram.h" + +#include + +#include "stdint.h" + +__attribute__((section(".aon"))) volatile uint32_t aonChecksum; +__attribute__((section(".aon"))) volatile uint8_t aonShadow[AONSHADOW_SIZE]; + +bool aonRamValid = false; + +void clearAonRam() { + memset((void *)0x130000, 0, 4096); +} + +bool loadValidateAonRam() { + uint32_t testchecksum = aonChecksum; + aonChecksum = 0x00000000; + uint32_t checksum = 0xABBA5FF5; + for (uint32_t c = 0x130000; c < 0x131000; c += 4) { + checksum += *(uint32_t *)c; + } + if (checksum == testchecksum) { + // immediately invalidate the checksum; if we reboot, we want a clean reboot + aonChecksum = 0x5445A00A; + memcpy((void *)(0x128000 - AONSHADOW_SIZE), (uint8_t*)aonShadow, AONSHADOW_SIZE); + return true; + } else { + clearAonRam(); + memset((void *)(0x128000 - AONSHADOW_SIZE), 0, AONSHADOW_SIZE); + return false; + } +} + +void saveAonRam() { + memcpy((uint8_t*)aonShadow, (void *)(0x128000 - AONSHADOW_SIZE), AONSHADOW_SIZE); + aonChecksum = 0x00000000; + uint32_t checksum = 0xABBA5FF5; + for (uint32_t c = 0x130000; c < 0x131000; c += 4) { + checksum += *(uint32_t *)c; + } + aonChecksum = checksum; +} diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.h new file mode 100644 index 00000000..4ad25f19 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.h @@ -0,0 +1,11 @@ +#include "stdint.h" +#include "stdbool.h" + + +#define AONSHADOW_SIZE 2048 + +extern bool aonRamValid; + +bool loadValidateAonRam(); +void saveAonRam(); +void clearAonRam(); \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_sleep.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_sleep.c index 888a81ce..58eaf6c6 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_sleep.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_sleep.c @@ -1,4 +1,4 @@ -#include +//#include #include #include "core_cm3.h" #include "mz100_gpio.h" @@ -14,6 +14,9 @@ #include "gpio.h" #include "main.h" #include "proto.h" +#include "printf.h" + +extern void saveAonRam(); void AON_level_VDD(int state) { @@ -90,9 +93,11 @@ extern struct AvailDataInfo curDataInfo; // last 'AvailDataInfo' we received fro extern bool requestPartialBlock; // if we should ask the AP to get this block from the host or not void sleep_with_with_wakeup(uint32_t sleep_time_ms) { - memcpy((uint8_t *)&(*(volatile unsigned int *)0x130500), (uint8_t *)&curBlock, sizeof(struct blockRequest)); - memcpy((uint8_t *)&(*(volatile unsigned int *)0x130600), (uint8_t *)&curDataInfo, sizeof(struct AvailDataInfo)); - printf("sleep: %u\r\n", sleep_time_ms); + saveAonRam(); + //memcpy((uint8_t *)&(*(volatile unsigned int *)0x130500), (uint8_t *)&curBlock, sizeof(struct blockRequest)); + //memcpy((uint8_t *)&(*(volatile unsigned int *)0x130600), (uint8_t *)&curDataInfo, sizeof(struct AvailDataInfo)); + //sleep_time_ms = 10000; + printf("sleep! %u\n", sleep_time_ms); uint32_t sleep_time_ms_1; AON_level_VDD(7); AON_level_VAA(0); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_sleep.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_sleep.h index bb997583..2ea346fb 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_sleep.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_sleep.h @@ -1,6 +1,6 @@ #pragma once -#include +//#include #include #include "core_cm3.h" #include "mz100_gpio.h" diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/nfc.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/nfc.c index 668b6a3a..0f85e977 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/nfc.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/nfc.c @@ -1,5 +1,5 @@ #include "nfc.h" -#include +//#include #include #include #include @@ -17,6 +17,8 @@ #include "timer.h" #include "epd.h" #include "proto.h" +#include "printf.h" + #define WHO_AM_I 0x04 uint8_t i2c_address = 0xAA; diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/nfc.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/nfc.h index 16708ad5..de8d121b 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/nfc.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/nfc.h @@ -1,5 +1,5 @@ #pragma once -#include +//#include #include #include #include diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c old mode 100644 new mode 100755 index 33bf4b10..2b74a077 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c @@ -3,64 +3,69 @@ #include #include #include -#include +// #include #include -#include "mz100_sleep.h" -#include "zigbee.h" -#include "eeprom.h" + #include "board.h" -#include "screen.h" +#include "eeprom.h" #include "main.h" -#include "util.h" +#include "mz100_sleep.h" +#include "printf.h" +#include "screen.h" #include "syncedproto.h" -#include +#include "util.h" +#include "zigbee.h" -uint16_t dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in -uint8_t dataReqAttemptArrayIndex = 0; -uint8_t dataReqLastAttempt = 0; -uint16_t nextCheckInFromAP = 0; -uint8_t wakeUpReason = 0; -uint8_t scanAttempts = 0; +__attribute__((section(".aonshadow"))) uint16_t dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in +__attribute__((section(".aonshadow"))) uint8_t dataReqAttemptArrayIndex = 0; +__attribute__((section(".aonshadow"))) uint8_t dataReqLastAttempt = 0; +__attribute__((section(".aonshadow"))) uint16_t nextCheckInFromAP = 0; +__attribute__((section(".aonshadow"))) uint8_t wakeUpReason = 0; +__attribute__((section(".aonshadow"))) uint8_t scanAttempts = 0; -int8_t temperature = 0; -uint16_t batteryVoltage = 0; -bool lowBattery = false; -uint16_t longDataReqCounter = 0; -uint16_t voltageCheckCounter = 0; +__attribute__((section(".aonshadow"))) int8_t temperature = 0; +__attribute__((section(".aonshadow"))) uint16_t batteryVoltage = 0; +__attribute__((section(".aonshadow"))) bool lowBattery = false; +__attribute__((section(".aonshadow"))) uint16_t longDataReqCounter = 0; +__attribute__((section(".aonshadow"))) uint16_t voltageCheckCounter = 0; -uint8_t capabilities = 0; +__attribute__((section(".aonshadow"))) uint8_t capabilities = 0; bool spiActive = false; bool uartActive = false; bool eepromActive = false; bool i2cActive = false; -extern int8_t adcSampleTemperature(void); // in degrees C -uint8_t checkButtonOrJig() -{ +extern int8_t adcSampleTemperature(void); // in degrees C + +uint8_t checkButtonOrJig() { return DETECT_P1_0_NOTHING; } -void setupPortsInitial() -{ +void setupPortsInitial() { } -void initPowerSaving(const uint16_t initialValue) -{ - for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) - { +uint16_t doVoltageReading() { + batteryVoltage = (uint16_t)measureBattery(); + if (batteryVoltage < BATTERY_VOLTAGE_MINIMUM) { + lowBattery = true; + } else { + lowBattery = false; + } + return batteryVoltage; +} + +void initPowerSaving(const uint16_t initialValue) { + for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { dataReqAttemptArr[c] = initialValue; } } -static void configSPI(const bool setup) -{ - +static void configSPI(const bool setup) { spiActive = setup; } -static void configUART(const bool setup) -{ +static void configUART(const bool setup) { /* if (setup == uartActive) return; uartActive = setup; @@ -70,69 +75,64 @@ static void configUART(const bool setup) Serial.end();*/ } -static void configEEPROM(const bool setup) -{ +static void configEEPROM(const bool setup) { } -static void configI2C(const bool setup) -{ +static void configI2C(const bool setup) { } -void powerUp(const uint8_t parts) -{ - printf("Power up: %d\r\n", parts); - if (parts & INIT_RADIO) - { +void powerUp(const uint8_t parts) { + // printf("Power up: %d\r\n", parts); + if (parts & INIT_RADIO) { radioInit(); // radioRxFilterCfg(mSelfMac, 0x10000, PROTO_PAN_ID); // radioSetTxPower(10); - if (currentChannel >= 11 && currentChannel <= 27) - { + if (currentChannel >= 11 && currentChannel <= 27) { radioSetChannel(currentChannel); - } - else - { + } else { radioSetChannel(RADIO_FIRST_CHANNEL); } } + if (parts & INIT_UART) { + configUART(true); + } + if (parts & INIT_EPD) { + configSPI(true); + } + if (parts & INIT_EEPROM) { + configEEPROM(true); + } + if (parts & INIT_I2C) { + configI2C(true); + } } -void powerDown(const uint8_t parts) -{ - printf("Power down: %d\r\n", parts); +void powerDown(const uint8_t parts) { + // printf("Power down: %d\r\n", parts); } -void doSleep(const uint32_t t) -{ +void doSleep(const uint32_t t) { printf("Sleeping for: %d ms\r\n", t); // sleepForMs(t); delay(t); } -uint32_t getNextScanSleep(const bool increment) -{ - if (increment) - { +uint32_t getNextScanSleep(const bool increment) { + if (increment) { if (scanAttempts < 255) scanAttempts++; } - if (scanAttempts < INTERVAL_1_ATTEMPTS) - { + if (scanAttempts < INTERVAL_1_ATTEMPTS) { return INTERVAL_1_TIME; - } - else if (scanAttempts < (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS)) - { + } else if (scanAttempts < (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS)) { return INTERVAL_2_TIME; - } - else - { + } else { return INTERVAL_3_TIME; } } -void addAverageValue() -{ +void addAverageValue() { uint16_t curval = INTERVAL_AT_MAX_ATTEMPTS - INTERVAL_BASE; curval *= dataReqLastAttempt; curval /= DATA_REQ_MAX_ATTEMPTS; @@ -141,14 +141,11 @@ void addAverageValue() dataReqAttemptArrayIndex++; } -uint16_t getNextSleep() -{ - /*uint16_t avg = 0; - for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) - { +uint16_t getNextSleep() { + uint16_t avg = 0; + for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { avg += dataReqAttemptArr[c]; } avg /= POWER_SAVING_SMOOTHING; - return avg;*/ - return 30; + return avg; } \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.h index 06ead2fe..eed0e059 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.h @@ -60,20 +60,22 @@ extern void doSleep(const uint32_t t); extern void addAverageValue(); extern uint16_t getNextSleep(); +extern uint16_t doVoltageReading(); + extern uint32_t getNextScanSleep(const bool increment); extern void initPowerSaving(const uint16_t initialValue); extern uint8_t wakeUpReason; -extern uint8_t capabilities; +extern __attribute__((section(".aonshadow"))) uint8_t capabilities; extern uint16_t nextCheckInFromAP; -extern uint8_t dataReqLastAttempt; -extern int8_t temperature; -extern uint16_t batteryVoltage; -extern bool lowBattery; -extern uint8_t scanAttempts; -extern uint16_t longDataReqCounter; -extern uint16_t voltageCheckCounter; +extern __attribute__((section(".aonshadow"))) uint8_t dataReqLastAttempt; +extern __attribute__((section(".aonshadow"))) int8_t temperature; +extern __attribute__((section(".aonshadow"))) uint16_t batteryVoltage; +extern __attribute__((section(".aonshadow"))) bool lowBattery; +extern __attribute__((section(".aonshadow"))) uint8_t scanAttempts; +extern __attribute__((section(".aonshadow"))) uint16_t longDataReqCounter; +extern __attribute__((section(".aonshadow"))) uint16_t voltageCheckCounter; #endif \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.c new file mode 100644 index 00000000..93029741 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.c @@ -0,0 +1,914 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "printf.h" + + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; + + +// internal buffer output +static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + + +// internal _putchar wrapper +static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)buffer; (void)idx; (void)maxlen; + if (character) { + _putchar(character); + } +} + + +// internal output function wrapper +static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)idx; (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); + } +} + + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char** str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) +{ + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } + else if (diff < 0.5) { + } + else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } + else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } + else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } + else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + + +// internal vsnprintf +static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) + { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } + else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } + else if (*format == 'o') { + base = 8U; + } + else if (*format == 'b') { + base = 2U; + } + else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } + else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); + } + else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + + +/////////////////////////////////////////////////////////////////////////////// + +int printf_(const char* format, ...) +{ + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int sprintf_(char* buffer, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int snprintf_(char* buffer, size_t count, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + + +int vprintf_(const char* format, va_list va) +{ + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); +} + + +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va) +{ + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + + +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) +{ + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = { out, arg }; + const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); + va_end(va); + return ret; +} diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.h new file mode 100644 index 00000000..821655b5 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.h @@ -0,0 +1,116 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. +// Use this instead of bloated standard/newlib printf. +// These routines are thread safe and reentrant. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Output a character to a custom device like UART, used by the printf() function + * This function is declared here only. You have to write your custom implementation somewhere + * \param character Character to output + */ +void _putchar(char character); + +/** + * Tiny printf implementation + * You have to implement _putchar if you use printf() + * To avoid conflicts with the regular printf() API it is overridden by macro defines + * and internal underscore-appended functions like printf_() are used + * \param format A string that specifies the format of the output + * \return The number of characters that are written into the array, not counting the terminating null character + */ +#define printf printf_ +int printf_(const char* format, ...); + + +/** + * Tiny sprintf implementation + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! + * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! + * \param format A string that specifies the format of the output + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define sprintf sprintf_ +int sprintf_(char* buffer, const char* format, ...); + + +/** + * Tiny snprintf/vsnprintf implementation + * \param buffer A pointer to the buffer where to store the formatted string + * \param count The maximum number of characters to store in the buffer, including a terminating null character + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that COULD have been written into the buffer, not counting the terminating + * null character. A value equal or larger than count indicates truncation. Only when the returned value + * is non-negative and less than count, the string has been completely written. + */ +#define snprintf snprintf_ +#define vsnprintf vsnprintf_ +int snprintf_(char* buffer, size_t count, const char* format, ...); +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); + + +/** + * Tiny vprintf implementation + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define vprintf vprintf_ +int vprintf_(const char* format, va_list va); + + +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() output + * \param out An output function which takes one character and an argument pointer + * \param arg An argument pointer for user data passed to output function + * \param format A string that specifies the format of the output + * \return The number of characters that are sent to the output function, not counting the terminating null character + */ +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); + + +#ifdef __cplusplus +} +#endif + + +#endif // _PRINTF_H_ diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/proto.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/proto.h index 19cd3fa2..e87d7326 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/proto.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/proto.h @@ -4,49 +4,49 @@ #include /* - All communications are direct from tag to station, EXCEPT association (tag will broadcast). - All comms shall be encrypted and authenticated with AES-CCM. Shared key shall be burned into the firmware. - Master shall provision new key at association. All non-bcast packets shall have pan id compression. - Master may skip "from" field. Tag checking in confirms it got the master's provisioning reply. - - Sadly filtering on MZ100 fails for long addr with no src addr. so short addr for src is used - - T = tag, S = station - - PACKET TYPE USE PAYLOAD STRUCT NOTES - ASSOC_REQ T2bcast TagInfo tag's info and assoc request (encrypted with shared key) - ASSOC_RESP S2T AssocInfo tag's association info (encrypted with shared key) - CHECKIN T2S CheckinInfo tag checking in occasionally - CHECKOUT S2T PendingInfo station's checkin reply telling tag what we have for it - CHUNK_REQ T2S ChunkReqInfo tag requesting a piece of data - CHUNK_RESP S2T ChunkInfo station provides chunk + All communications are direct from tag to station, EXCEPT association (tag will broadcast). + All comms shall be encrypted and authenticated with AES-CCM. Shared key shall be burned into the firmware. + Master shall provision new key at association. All non-bcast packets shall have pan id compression. + Master may skip "from" field. Tag checking in confirms it got the master's provisioning reply. + + Sadly filtering on MZ100 fails for long addr with no src addr. so short addr for src is used + + T = tag, S = station + + PACKET TYPE USE PAYLOAD STRUCT NOTES + ASSOC_REQ T2bcast TagInfo tag's info and assoc request (encrypted with shared key) + ASSOC_RESP S2T AssocInfo tag's association info (encrypted with shared key) + CHECKIN T2S CheckinInfo tag checking in occasionally + CHECKOUT S2T PendingInfo station's checkin reply telling tag what we have for it + CHUNK_REQ T2S ChunkReqInfo tag requesting a piece of data + CHUNK_RESP S2T ChunkInfo station provides chunk */ -#define PROTO_PRESHARED_KEY {0x34D906D3, 0xE3E5298E, 0x3429BF58, 0xC1022081} +#define PROTO_PRESHARED_KEY \ + { 0x34D906D3, 0xE3E5298E, 0x3429BF58, 0xC1022081 } -#define PROTO_PAN_ID (0x4447) //PAN ID compression shall be used +#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used -#define PKT_ASSOC_REQ (0xF0) -#define PKT_ASSOC_RESP (0xF1) -#define PKT_CHECKIN (0xF2) -#define PKT_CHECKOUT (0xF3) -#define PKT_CHUNK_REQ (0xF4) -#define PKT_CHUNK_RESP (0xF5) +#define PKT_ASSOC_REQ (0xF0) +#define PKT_ASSOC_RESP (0xF1) +#define PKT_CHECKIN (0xF2) +#define PKT_CHECKOUT (0xF3) +#define PKT_CHUNK_REQ (0xF4) +#define PKT_CHUNK_RESP (0xF5) -#define PROTO_VER_0 (0) -#define PROTO_VER_CURRENT (PROTO_VER_0) +#define PROTO_VER_0 (0) +#define PROTO_VER_CURRENT (PROTO_VER_0) -#define PROTO_COMPR_TYPE_LZ (0x0001) -#define PROTO_COMPR_TYPE_BITPACK (0x0002) - -#define PROTO_MAX_DL_LEN (88) +#define PROTO_COMPR_TYPE_LZ (0x0001) +#define PROTO_COMPR_TYPE_BITPACK (0x0002) +#define PROTO_MAX_DL_LEN (88) //////////////// NEW #include "tag_types.h" - +/* // power saving algorithm #define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA) #define INTERVAL_AT_MAX_ATTEMPTS 600 // interval (in seconds) (at max attempts) for target average current @@ -68,7 +68,7 @@ #define INTERVAL_2_TIME 7200UL // Try every 2 hours #define INTERVAL_2_ATTEMPTS 12 // for 12 attempts (an additional day) #define INTERVAL_3_TIME 86400UL // Finally, try every day - +*/ #pragma pack(1) enum TagScreenType { TagScreenEink_BW_1bpp, @@ -96,8 +96,6 @@ enum TagScreenType { TagScreenTypeOther = 0x7f, }; - - #define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc #define ADDR_MODE_NONE (0) @@ -122,7 +120,7 @@ struct MacFcs { uint8_t destAddrType : 2; uint8_t frameVer : 2; uint8_t srcAddrType : 2; -} ; +}; struct MacFrameFromMaster { struct MacFcs fcs; @@ -130,7 +128,7 @@ struct MacFrameFromMaster { uint16_t pan; uint8_t dst[8]; uint16_t from; -} ; +}; struct MacFrameNormal { struct MacFcs fcs; @@ -138,7 +136,7 @@ struct MacFrameNormal { uint16_t pan; uint8_t dst[8]; uint8_t src[8]; -} ; +}; struct MacFrameBcast { struct MacFcs fcs; @@ -147,7 +145,7 @@ struct MacFrameBcast { uint16_t dstAddr; uint16_t srcPan; uint8_t src[8]; -} ; +}; #define PKT_AVAIL_DATA_SHORTREQ 0xE3 #define PKT_AVAIL_DATA_REQ 0xE5 @@ -175,7 +173,7 @@ struct AvailDataReq { uint8_t currentChannel; uint8_t customMode; uint8_t reserved[8]; -} ; +}; struct oldAvailDataReq { uint8_t checksum; @@ -186,7 +184,7 @@ struct oldAvailDataReq { uint8_t hwType; uint8_t wakeupReason; uint8_t capabilities; -} ; +}; struct AvailDataInfo { uint8_t checksum; @@ -195,31 +193,31 @@ struct AvailDataInfo { uint8_t dataType; uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image) uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes -} ; +} __attribute__((packed)) ; struct pendingData { struct AvailDataInfo availdatainfo; uint16_t attemptsLeft; uint8_t targetMac[8]; -} ; +}; struct blockPart { uint8_t checksum; uint8_t blockId; uint8_t blockPart; uint8_t data[]; -} ; +}; struct blockData { uint16_t size; uint16_t checksum; uint8_t data[]; -} ; +}; struct burstMacData { uint16_t offset; uint8_t targetMac[8]; -} ; +}; #define BLOCK_PART_DATA_SIZE 99 #define BLOCK_MAX_PARTS 42 @@ -238,140 +236,131 @@ struct blockRequest { struct blockRequestAck { uint8_t checksum; uint16_t pleaseWaitMs; -} ; +}; struct espBlockRequest { uint8_t checksum; uint64_t ver; uint8_t blockId; uint8_t src[8]; -} ; +}; struct espXferComplete { uint8_t checksum; uint8_t src[8]; -} ; +}; struct espAvailDataReq { uint8_t checksum; uint8_t src[8]; struct AvailDataReq adr; -} ; +}; struct espSetChannelPower { uint8_t checksum; uint8_t channel; uint8_t power; -} ; +}; #pragma pack(0) ///////////////// NEW END #ifndef __packed -#define __packed __attribute__((packed)) +#define __packed __attribute__((packed)) #endif struct TagState { - uint64_t swVer; - uint16_t hwType; - uint16_t batteryMv; + uint64_t swVer; + uint16_t hwType; + uint16_t batteryMv; } __packed; struct TagInfo { - uint8_t protoVer; //PROTO_VER_* - struct TagState state; - uint8_t rfu1[1]; //shall be ignored for now - uint16_t screenPixWidth; - uint16_t screenPixHeight; - uint16_t screenMmWidth; - uint16_t screenMmHeight; - uint16_t compressionsSupported; //COMPR_TYPE_* bitfield - uint16_t maxWaitMsec; //how long tag will wait for packets before going to sleep - uint8_t screenType; //enum TagScreenType - uint8_t rfu[11]; //shall be zero for now + uint8_t protoVer; // PROTO_VER_* + struct TagState state; + uint8_t rfu1[1]; // shall be ignored for now + uint16_t screenPixWidth; + uint16_t screenPixHeight; + uint16_t screenMmWidth; + uint16_t screenMmHeight; + uint16_t compressionsSupported; // COMPR_TYPE_* bitfield + uint16_t maxWaitMsec; // how long tag will wait for packets before going to sleep + uint8_t screenType; // enum TagScreenType + uint8_t rfu[11]; // shall be zero for now } __packed; struct AssocInfo { - uint32_t checkinDelay; //space between checkins, in msec - uint32_t retryDelay; //if download fails mid-way wait thi smany msec to retry (IFF progress was made) - uint16_t failedCheckinsTillBlank; //how many fails till we go blank - uint16_t failedCheckinsTillDissoc; //how many fails till we dissociate - uint32_t newKey[4]; - uint8_t rfu[8]; //shall be zero for now + uint32_t checkinDelay; // space between checkins, in msec + uint32_t retryDelay; // if download fails mid-way wait thi smany msec to retry (IFF progress was made) + uint16_t failedCheckinsTillBlank; // how many fails till we go blank + uint16_t failedCheckinsTillDissoc; // how many fails till we dissociate + uint32_t newKey[4]; + uint8_t rfu[8]; // shall be zero for now } __packed; -#define CHECKIN_TEMP_OFFSET 0x7f +#define CHECKIN_TEMP_OFFSET 0x7f struct CheckinInfo { - struct TagState state; - uint8_t lastPacketLQI; //zero if not reported/not supported to be reported - int8_t lastPacketRSSI; //zero if not reported/not supported to be reported - uint8_t temperature; //zero if not reported/not supported to be reported. else, this minus CHECKIN_TEMP_OFFSET is temp in degrees C - uint8_t rfu[6]; //shall be zero for now + struct TagState state; + uint8_t lastPacketLQI; // zero if not reported/not supported to be reported + int8_t lastPacketRSSI; // zero if not reported/not supported to be reported + uint8_t temperature; // zero if not reported/not supported to be reported. else, this minus CHECKIN_TEMP_OFFSET is temp in degrees C + uint8_t rfu[6]; // shall be zero for now } __packed; struct PendingInfo { - uint64_t imgUpdateVer; - uint32_t imgUpdateSize; - uint64_t osUpdateVer; //version of OS update avail - uint32_t osUpdateSize; - uint8_t rfu[8]; //shall be zero for now + uint64_t imgUpdateVer; + uint32_t imgUpdateSize; + uint64_t osUpdateVer; // version of OS update avail + uint32_t osUpdateSize; + uint8_t rfu[8]; // shall be zero for now } __packed; struct ChunkReqInfo { - uint64_t versionRequested; - uint32_t offset; - uint8_t len; - uint8_t osUpdatePlz : 1; - uint8_t rfu[6]; //shall be zero for now + uint64_t versionRequested; + uint32_t offset; + uint8_t len; + uint8_t osUpdatePlz : 1; + uint8_t rfu[6]; // shall be zero for now } __packed; struct ChunkInfo { - uint32_t offset; - uint8_t osUpdatePlz : 1; - uint8_t rfu; //shall be zero for now - uint8_t data[]; //no data means request is out of bounds of this version no longer exists + uint32_t offset; + uint8_t osUpdatePlz : 1; + uint8_t rfu; // shall be zero for now + uint8_t data[]; // no data means request is out of bounds of this version no longer exists } __packed; +#define MACFMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" +#define MACCVT(x) ((const uint8_t*)(x))[7], ((const uint8_t*)(x))[6], ((const uint8_t*)(x))[5], ((const uint8_t*)(x))[4], ((const uint8_t*)(x))[3], ((const uint8_t*)(x))[2], ((const uint8_t*)(x))[1], ((const uint8_t*)(x))[0] +#define VERSION_SIGNIFICANT_MASK (0x0000ffffffffffffull) -#define MACFMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" -#define MACCVT(x) ((const uint8_t*)(x))[7], ((const uint8_t*)(x))[6], ((const uint8_t*)(x))[5], ((const uint8_t*)(x))[4], ((const uint8_t*)(x))[3], ((const uint8_t*)(x))[2], ((const uint8_t*)(x))[1], ((const uint8_t*)(x))[0] +#define HW_TYPE_42_INCH_SAMSUNG (1) +#define HW_TYPE_42_INCH_SAMSUNG_ROM_VER_OFST (0xEFF8) +#define HW_TYPE_74_INCH_DISPDATA (2) +#define HW_TYPE_74_INCH_DISPDATA_FRAME_MODE (3) +#define HW_TYPE_74_INCH_DISPDATA_ROM_VER_OFST (0x008b) -#define VERSION_SIGNIFICANT_MASK (0x0000ffffffffffffull) +#define HW_TYPE_ZBD_EPOP50 (4) +#define HW_TYPE_ZBD_EPOP50_ROM_VER_OFST (0x008b) -#define HW_TYPE_42_INCH_SAMSUNG (1) -#define HW_TYPE_42_INCH_SAMSUNG_ROM_VER_OFST (0xEFF8) +#define HW_TYPE_ZBD_EPOP900 (5) +#define HW_TYPE_ZBD_EPOP900_ROM_VER_OFST (0x008b) -#define HW_TYPE_74_INCH_DISPDATA (2) -#define HW_TYPE_74_INCH_DISPDATA_FRAME_MODE (3) -#define HW_TYPE_74_INCH_DISPDATA_ROM_VER_OFST (0x008b) - -#define HW_TYPE_ZBD_EPOP50 (4) -#define HW_TYPE_ZBD_EPOP50_ROM_VER_OFST (0x008b) - -#define HW_TYPE_ZBD_EPOP900 (5) -#define HW_TYPE_ZBD_EPOP900_ROM_VER_OFST (0x008b) - -#define HW_TYPE_29_INCH_DISPDATA (6) -#define HW_TYPE_29_INCH_DISPDATA_FRAME_MODE (7) -#define HW_TYPE_29_INCH_DISPDATA_ROM_VER_OFST (0x008b) - -#define HW_TYPE_29_INCH_ZBS_026 (8) -#define HW_TYPE_29_INCH_ZBS_026_FRAME_MODE (9) -#define HW_TYPE_29_INCH_ZBS_025 (10) -#define HW_TYPE_29_INCH_ZBS_025_FRAME_MODE (11) -#define HW_TYPE_29_INCH_ZBS_ROM_VER_OFST (0x008b) - -#define HW_TYPE_74_INCH_BWR (40) -#define HW_TYPE_74_INCH_BWR_ROM_VER_OFST (0x0160) -#define HW_TYPE_58_INCH_BWR (41) -#define HW_TYPE_58_INCH_BWR_ROM_VER_OFST (0x0160) -#define HW_TYPE_42_INCH_BWR (42) -#define HW_TYPE_42_INCH_BWR_ROM_VER_OFST (0x0160) +#define HW_TYPE_29_INCH_DISPDATA (6) +#define HW_TYPE_29_INCH_DISPDATA_FRAME_MODE (7) +#define HW_TYPE_29_INCH_DISPDATA_ROM_VER_OFST (0x008b) +#define HW_TYPE_29_INCH_ZBS_026 (8) +#define HW_TYPE_29_INCH_ZBS_026_FRAME_MODE (9) +#define HW_TYPE_29_INCH_ZBS_025 (10) +#define HW_TYPE_29_INCH_ZBS_025_FRAME_MODE (11) +#define HW_TYPE_29_INCH_ZBS_ROM_VER_OFST (0x008b) +#define HW_TYPE_74_INCH_BWR (40) +#define HW_TYPE_74_INCH_BWR_ROM_VER_OFST (0x0160) +#define HW_TYPE_58_INCH_BWR (41) +#define HW_TYPE_58_INCH_BWR_ROM_VER_OFST (0x0160) +#define HW_TYPE_42_INCH_BWR (42) +#define HW_TYPE_42_INCH_BWR_ROM_VER_OFST (0x0160) #endif - - - - diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.c index fb452c15..44636885 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.c @@ -3,143 +3,24 @@ #include "eeprom.h" #include "util.h" #include "mz100_flash.h" +#include "powermgt.h" + + __attribute__((section(".aonshadow"))) struct tagsettings tagSettings = {0}; +extern uint8_t blockXferBuffer[]; +uint8_t* infopageTempBuffer = 1024 + blockXferBuffer; -#define EEPROM_NUM_SETTINGS_PAGES (EEPROM_SETTINGS_AREA_LEN / EEPROM_PAGE_SIZE) -#define SETTINGS_MAGIC (0x31415926) - - - -static uint32_t mCurSettingsAddr; - -static void settingsPrvDoWriteAtLocation(uint32_t addr, struct Settings* settings) -{ - settings->hdr.revision++; - mCurSettingsAddr = addr; - FLASH_Write(false, addr, (uint8_t*)settings, sizeof(struct Settings)); -} - -//this is impossible to call before calling read. thus mCurSettingsAddr will be set -void settingsPrvDoWrite(struct Settings* settings) -{ - struct SettingsHeader sh; - uint32_t i, addr; - uint8_t byte; - - - //first we try to fit in the current page, after current (latest) settings - if (mCurSettingsAddr) { - - FLASH_Read(0, mCurSettingsAddr, (uint8_t*)&sh, sizeof(struct SettingsHeader)); - addr = mCurSettingsAddr + sh.structSize; - - //is there space? - if (addr % EEPROM_PAGE_SIZE != 0 && addr % EEPROM_PAGE_SIZE + sizeof(struct Settings) <= EEPROM_PAGE_SIZE) { - - //is it erased - for (i = 0; i < sizeof(struct Settings); i++) { - - FLASH_Read(0, addr, &byte, 1); - if (byte != 0xff) - break; - } - - if (i == sizeof(struct Settings)) { - - settingsPrvDoWriteAtLocation(addr, settings); - return; - } - } - } - - //we need to erase - use next page (or 0th page if no current page at all) - if (mCurSettingsAddr) { - - addr = (mCurSettingsAddr + EEPROM_PAGE_SIZE - 1) / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE; - if (addr == EEPROM_SETTINGS_AREA_START + EEPROM_SETTINGS_AREA_LEN) - addr = EEPROM_SETTINGS_AREA_START; - } - else - addr = EEPROM_SETTINGS_AREA_START; - - qspiEraseRange(addr, EEPROM_PAGE_SIZE); - settingsPrvDoWriteAtLocation(addr, settings); -} - -void settingsRead(struct Settings* settings) -{ - uint32_t bestAddr = 0, page, ofst; - uint64_t bestRevision = 0; - struct SettingsHeader sh; - bool doWrite = true; - - for (page = 0; page < EEPROM_NUM_SETTINGS_PAGES; page++) { - - for (ofst = 0; ofst < EEPROM_PAGE_SIZE - sizeof(struct SettingsHeader); ofst += sh.structSize) { - - uint32_t addr = EEPROM_SETTINGS_AREA_START + page * EEPROM_PAGE_SIZE + ofst; - - FLASH_Read(0, addr, (uint8_t*)&sh, sizeof(struct SettingsHeader)); - - //sanity checks. struct is only allowed to grow in size... - if (sh.magic != SETTINGS_MAGIC || ofst + sh.structSize > EEPROM_PAGE_SIZE || sh.structSize > sizeof(struct Settings)) - break; - - if (sh.revision > bestRevision) { - bestRevision = sh.revision; - bestAddr = addr; - } - } - } - - if (bestAddr) { - FLASH_Read(0, bestAddr, (uint8_t*)&sh, sizeof(struct SettingsHeader)); //to get size - FLASH_Read(0, bestAddr, (uint8_t*)settings, sh.structSize); - mCurSettingsAddr = bestAddr; - } - else { - settings->hdr.structVersion = SETTINGS_VER_NONE; - settings->hdr.revision = 1; - mCurSettingsAddr = 0; - } - - //migrate - switch (settings->hdr.structVersion) { - - //current version here - mark as such - case SETTINGS_CURRENT: - doWrite = false; - break; - - case SETTINGS_VER_NONE: //migrate to v1 - memset(settings, 0, sizeof(*settings)); - settings->hdr.magic = SETTINGS_MAGIC; - //fallthrough - - case SETTINGS_VER_1: //migrate to v2 - settings->prevDlProgress = 0xffff; - //fallthrough - - case SETTINGS_VER_2: //migrate to v3 - settings->lastRxedRSSI = 0; - //fallthrough - - //new migrations here in order from lower vers to higher vers - - settings->hdr.structVersion = SETTINGS_CURRENT; - settings->hdr.structSize = sizeof(struct Settings); - break; - } - - if (doWrite) - settingsPrvDoWrite(settings); -} - -void settingsWrite(struct Settings* settings) -{ - struct Settings s; - - settingsRead(&s); - if (memcmp(&s, settings, sizeof(struct Settings))) - settingsPrvDoWrite(settings); +void loadDefaultSettings() { + tagSettings.settingsVer = SETTINGS_STRUCT_VERSION; + tagSettings.enableFastBoot = DEFAULT_SETTING_FASTBOOT; + tagSettings.enableRFWake = DEFAULT_SETTING_RFWAKE; + tagSettings.enableTagRoaming = DEFAULT_SETTING_TAGROAMING; + tagSettings.enableScanForAPAfterTimeout = DEFAULT_SETTING_SCANFORAP; + tagSettings.enableLowBatSymbol = DEFAULT_SETTING_LOWBATSYMBOL; + tagSettings.enableNoRFSymbol = DEFAULT_SETTING_NORFSYMBOL; + tagSettings.customMode = 0; + tagSettings.fastBootCapabilities = 0; + tagSettings.minimumCheckInTime = INTERVAL_BASE; + tagSettings.fixedChannel = 0; + tagSettings.batLowVoltage = BATTERY_VOLTAGE_MINIMUM; } \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.h index 9da5fff7..d45efc05 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.h @@ -1,65 +1,41 @@ -#ifndef _SETTINGS_H_ -#define _SETTINGS_H_ +#ifndef SETTINGS_H +#define SETTINGS_H #include -#define SETTINGS_VER_NONE (0x00000000) -#define SETTINGS_VER_1 (0x00000001) -#define SETTINGS_VER_2 (0x00000002) -#define SETTINGS_VER_3 (0x00000003) +#define FW_VERSION 20 // version number (max 2.5.5 :) ) +#define FW_VERSION_SUFFIX "-75" // suffix, like -RC1 or whatever. +// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers +// #define PRINT_LUT // uncomment if you want the tag to print the LUT for the current temperature bracket -struct SettingsHeader { - uint32_t magic; - uint64_t revision; - uint8_t structVersion; - uint8_t structSize; //incl this header +#define SETTINGS_STRUCT_VERSION 0x01 + +#define DEFAULT_SETTING_FASTBOOT 0 +#define DEFAULT_SETTING_RFWAKE 0 +#define DEFAULT_SETTING_TAGROAMING 0 +#define DEFAULT_SETTING_SCANFORAP 1 +#define DEFAULT_SETTING_LOWBATSYMBOL 1 +#define DEFAULT_SETTING_NORFSYMBOL 1 + +struct tagsettings { + uint8_t settingsVer; // the version of the struct as written to the infopage + uint8_t enableFastBoot; // default 0; if set, it will skip splashscreen + uint8_t enableRFWake; // default 0; if set, it will enable RF wake. This will add about ~0.9µA idle power consumption + uint8_t enableTagRoaming; // default 0; if set, the tag will scan for an accesspoint every few check-ins. This will increase power consumption quite a bit + uint8_t enableScanForAPAfterTimeout; // default 1; if a the tag failed to check in, after a few attempts it will try to find a an AP on other channels + uint8_t enableLowBatSymbol; // default 1; tag will show 'low battery' icon on screen if the battery is depleted + uint8_t enableNoRFSymbol; // default 1; tag will show 'no signal' icon on screen if it failed to check in for a longer period of time + uint8_t fastBootCapabilities; // holds the byte with 'capabilities' as detected during a normal tag boot; allows the tag to skip detecting buttons and NFC chip + uint8_t customMode; // default 0; if anything else, tag will bootup in a different 'mode' + uint16_t batLowVoltage; // Low battery threshold voltage (2450 for 2.45v). defaults to BATTERY_VOLTAGE_MINIMUM from powermgt.h + uint16_t minimumCheckInTime; // defaults to BASE_INTERVAL from powermgt.h + uint8_t fixedChannel; // default 0; if set to a valid channel number, the tag will stick to that channel } __attribute__((packed)); -enum SettingsThingType { - SettingsThingTypeNone, - SettingsThingTypeImage, - SettingsThingTypeUpdate, -}; +extern __attribute__((section(".aonshadow")))struct tagsettings tagSettings; -#define SETTING_CHANNEL_OFFSET 11 - -struct Settings { //V1 - struct SettingsHeader hdr; - - //master address - uint8_t masterMac[8]; - - //encryption things - uint32_t encrKey[4]; - uint32_t nextIV; - - //checkin tracking - uint32_t checkinDelay; //space between checkins, in msec - uint32_t retryDelay; - uint16_t failedCheckinsTillBlank; //how many fails till we go blank - uint16_t failedCheckinsTillDissoc; //how many fails till we dissociate - uint16_t numFailedCheckins; - - //state - uint8_t lastRxedLQI; - uint8_t isPaired : 1; - uint8_t channel : 4; //minus SETTING_CHANNEL_OFFSET - uint8_t reserved : 3; - - uint16_t prevDlProgress; - - int8_t lastRxedRSSI; - uint32_t helperInit; - -} __attribute__((packed)); - -#define SETTINGS_CURRENT SETTINGS_VER_3 - - -void settingsRead(struct Settings* settings); -void settingsWrite(struct Settings* settings); - - - - -#endif +void loadDefaultSettings(); +void writeSettings(); +void loadSettings(); +void loadSettingsFromBuffer(uint8_t* p); +#endif \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.c index 916d4556..75c2b0da 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.c @@ -1,127 +1,111 @@ -#include "main.h" -#include "timer.h" -#include "zigbee.h" -#include "util.h" -#include "mz100_sleep.h" -#include "proto.h" #include "syncedproto.h" -#include "comms.h" + #include "board.h" -#include "eeprom.h" -#include "powermgt.h" -#include "util.h" +#include "comms.h" #include "drawing.h" +#include "eeprom.h" +#include "main.h" +#include "mz100_sleep.h" +#include "powermgt.h" +#include "proto.h" +#include "timer.h" +#include "util.h" +#include "zigbee.h" +#include "printf.h" // download-stuff uint8_t blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0}; -struct blockRequest curBlock = {0}; // used by the block-requester, contains the next request that we'll send -struct AvailDataInfo curDataInfo = {0}; // last 'AvailDataInfo' we received from the AP -bool requestPartialBlock = false; // if we should ask the AP to get this block from the host or not +__attribute__((section(".aonshadow"))) struct blockRequest curBlock = {0}; // used by the block-requester, contains the next request that we'll send +__attribute__((section(".aonshadow"))) struct AvailDataInfo curDataInfo = {0}; // last 'AvailDataInfo' we received from the AP +bool requestPartialBlock = false; // if we should ask the AP to get this block from the host or not #define BLOCK_TRANSFER_ATTEMPTS 10 -uint8_t prevImgSlot = 0xFF; -uint8_t curImgSlot = 0xFF; -static uint32_t curHighSlotId = 0; -static uint8_t nextImgSlot = 0; -static uint8_t imgSlots = 0; -uint8_t drawWithLut = 0; +__attribute__((section(".aonshadow"))) uint8_t prevImgSlot = 0xFF; +__attribute__((section(".aonshadow"))) uint8_t curImgSlot = 0xFF; +__attribute__((section(".aonshadow"))) static uint32_t curHighSlotId = 0; +__attribute__((section(".aonshadow"))) static uint8_t nextImgSlot = 0; +__attribute__((section(".aonshadow"))) static uint8_t imgSlots = 0; +__attribute__((section(".aonshadow"))) uint8_t drawWithLut = 0; // stuff we need to keep track of related to the network/AP uint8_t APmac[8] = {0}; uint16_t APsrcPan = 0; -uint8_t mSelfMac[8] = {0}; -static uint8_t seq = 0; -uint8_t currentChannel = 0; +__attribute__((section(".aonshadow"))) uint8_t mSelfMac[8] = {0}; +__attribute__((section(".aonshadow"))) static uint8_t seq = 0; +__attribute__((section(".aonshadow"))) volatile uint8_t currentChannel = 0; // buffer we use to prepare/read packets static uint8_t inBuffer[128] = {0}; static uint8_t outBuffer[128] = {0}; +// #define DEBUGBLOCKS 1 + // tools -static uint8_t getPacketType(const void *buffer) -{ +static uint8_t getPacketType(const void *buffer) { const struct MacFcs *fcs = buffer; - if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) - { + if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) { // broadcast frame uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameBcast)]; return type; - } - else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) - { + } else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) { // normal frame uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameNormal)]; return type; } return 0; } -static bool pktIsUnicast(const void *buffer) -{ +static bool pktIsUnicast(const void *buffer) { const struct MacFcs *fcs = buffer; - if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) - { + if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) { return false; - } - else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) - { + } else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) { // normal frame return true; } // unknown type... return false; } -void dump(const uint8_t *a, const uint16_t l) -{ +void dump(const uint8_t *a, const uint16_t l) { printf("\n "); #define ROWS 16 - for (uint8_t c = 0; c < ROWS; c++) - { + for (uint8_t c = 0; c < ROWS; c++) { printf(" %02X", c); } printf("\n--------"); - for (uint8_t c = 0; c < ROWS; c++) - { + for (uint8_t c = 0; c < ROWS; c++) { printf("---"); } - for (uint16_t c = 0; c < l; c++) - { - if ((c % ROWS) == 0) - { + for (uint16_t c = 0; c < l; c++) { + if ((c % ROWS) == 0) { printf("\n0x%04X | ", c); } printf("%02X ", a[c]); } printf("\n--------"); - for (uint8_t c = 0; c < ROWS; c++) - { + for (uint8_t c = 0; c < ROWS; c++) { printf("---"); } printf("\n"); } -static bool checkCRC(const void *p, const uint8_t len) -{ +static bool checkCRC(const void *p, const uint8_t len) { uint8_t total = 0; - for (uint8_t c = 1; c < len; c++) - { + for (uint8_t c = 1; c < len; c++) { total += ((uint8_t *)p)[c]; } // printf("CRC: rx %d, calc %d\n", ((uint8_t *)p)[0], total); return ((uint8_t *)p)[0] == total; } -static void addCRC(void *p, const uint8_t len) -{ +static void addCRC(void *p, const uint8_t len) { uint8_t total = 0; - for (uint8_t c = 1; c < len; c++) - { + for (uint8_t c = 1; c < len; c++) { total += ((uint8_t *)p)[c]; } ((uint8_t *)p)[0] = total; } // radio stuff -static void sendPing() -{ +static void sendPing() { struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1); memset(outBuffer, 0, sizeof(struct MacFrameBcast) + 2 + 4); outBuffer[0] = sizeof(struct MacFrameBcast) + 1 + 2; @@ -137,26 +121,20 @@ static void sendPing() txframe->srcPan = PROTO_PAN_ID; commsTxNoCpy(outBuffer); } -uint8_t detectAP(const uint8_t channel) -{ +uint8_t detectAP(const uint8_t channel) { uint32_t t; radioRxEnable(false); radioSetChannel(channel); radioRxFlush(); radioRxEnable(true); - for (uint8_t c = 1; c <= MAXIMUM_PING_ATTEMPTS; c++) - { + for (uint8_t c = 1; c <= MAXIMUM_PING_ATTEMPTS; c++) { sendPing(); t = timerGet() + (TIMER_TICKS_PER_MSEC * 5); - while (timerGet() < t) - { + while (timerGet() < t) { int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) - { - if ((inBuffer[sizeof(struct MacFrameNormal) + 1] == channel) && (getPacketType(inBuffer) == PKT_PONG)) - { - if (pktIsUnicast(inBuffer)) - { + if (ret > 1) { + if ((inBuffer[sizeof(struct MacFrameNormal) + 1] == channel) && (getPacketType(inBuffer) == PKT_PONG)) { + if (pktIsUnicast(inBuffer)) { // dump(inBuffer,32); struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer; memcpy(APmac, f->src, 8); @@ -165,29 +143,27 @@ uint8_t detectAP(const uint8_t channel) } } } - timerDelay(TIMER_TICKS_PER_MSEC * 1); + timerDelay(TIMER_TICKS_PER_MSEC * 2); } } return 0; } // data xfer stuff -static void sendShortAvailDataReq() -{ +static void sendShortAvailDataReq() { struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1); outBuffer[0] = sizeof(struct MacFrameBcast) + 1 + 2; outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_AVAIL_DATA_SHORTREQ; memcpy(txframe->src, mSelfMac, 8); outBuffer[1] = 0x21; - outBuffer[2] = 0xC8; // quickly set txframe fcs structure for broadcast packet + outBuffer[2] = 0xC8; // quickly set txframe fcs structure for broadcast packet txframe->seq = seq++; txframe->dstPan = PROTO_PAN_ID; txframe->dstAddr = 0xFFFF; txframe->srcPan = PROTO_PAN_ID; commsTxNoCpy(outBuffer); } -static void sendAvailDataReq() -{ +static void sendAvailDataReq() { struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1); memset(outBuffer, 0, sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 4); struct AvailDataReq *availreq = (struct AvailDataReq *)(outBuffer + 2 + sizeof(struct MacFrameBcast)); @@ -203,7 +179,7 @@ static void sendAvailDataReq() txframe->dstAddr = 0xFFFF; txframe->srcPan = PROTO_PAN_ID; // TODO: send some (more) meaningful data - availreq->hwType = HW_TYPE; + availreq->hwType = 5; availreq->wakeupReason = wakeUpReason; availreq->lastPacketRSSI = mLastRSSI; availreq->lastPacketLQI = mLastLqi; @@ -213,27 +189,22 @@ static void sendAvailDataReq() addCRC(availreq, sizeof(struct AvailDataReq)); commsTxNoCpy(outBuffer); } -struct AvailDataInfo *getAvailDataInfo() -{ +struct AvailDataInfo *getAvailDataInfo() { radioRxEnable(true); uint32_t t; - for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) - { + for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) { sendAvailDataReq(); - t = timerGet() + (TIMER_TICKS_PER_MSEC * DATA_REQ_RX_WINDOW_SIZE); - while (timerGet() < t) - { + t = timerGet() + (TIMER_TICKS_PER_MSEC * (DATA_REQ_RX_WINDOW_SIZE + 2)); + while (timerGet() < t) { int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) - { - if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO) - { - if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo))) - { + if (ret > 1) { + if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO) { + if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo))) { struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer; memcpy(APmac, f->src, 8); APsrcPan = f->pan; dataReqLastAttempt = c; + printf("%d", dataReqLastAttempt); return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1); } } @@ -243,28 +214,23 @@ struct AvailDataInfo *getAvailDataInfo() dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS; return NULL; } -struct AvailDataInfo *getShortAvailDataInfo() -{ +struct AvailDataInfo *getShortAvailDataInfo() { radioRxEnable(true); uint32_t t; - for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) - { + for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) { sendShortAvailDataReq(); // sendAvailDataReq(); t = timerGet() + (TIMER_TICKS_PER_MSEC * 25); - while (timerGet() < t) - { + while (timerGet() < t) { int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) - { - if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO) - { - if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo))) - { + if (ret > 1) { + if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO) { + if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo))) { struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer; memcpy(APmac, f->src, 8); APsrcPan = f->pan; dataReqLastAttempt = c; + printf("%d", dataReqLastAttempt); return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1); } } @@ -274,13 +240,11 @@ struct AvailDataInfo *getShortAvailDataInfo() dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS; return NULL; } -static bool processBlockPart(const struct blockPart *bp) -{ +static bool processBlockPart(const struct blockPart *bp) { uint16_t start = bp->blockPart * BLOCK_PART_DATA_SIZE; uint16_t size = BLOCK_PART_DATA_SIZE; // validate if it's okay to copy data - if (bp->blockId != curBlock.blockId) - { + if (bp->blockId != curBlock.blockId) { // printf("got a packet for block %02X\n", bp->blockId); return false; } @@ -288,36 +252,28 @@ static bool processBlockPart(const struct blockPart *bp) return false; if (bp->blockPart > BLOCK_MAX_PARTS) return false; - if ((start + size) > sizeof(blockXferBuffer)) - { + if ((start + size) > sizeof(blockXferBuffer)) { size = sizeof(blockXferBuffer) - start; } - if (checkCRC(bp, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE)) - { + if (checkCRC(bp, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE)) { // copy block data to buffer memcpy((void *)(blockXferBuffer + start), (const void *)bp->data, size); // we don't need this block anymore, set bit to 0 so we don't request it again curBlock.requestedParts[bp->blockPart / 8] &= ~(1 << (bp->blockPart % 8)); return true; - } - else - { + } else { return false; } } -static bool blockRxLoop(const uint32_t timeout) -{ +static bool blockRxLoop(const uint32_t timeout) { uint32_t t; bool success = false; radioRxEnable(true); t = timerGet() + (TIMER_TICKS_PER_MSEC * (timeout + 20)); - while (timerGet() < t) - { + while (timerGet() < t) { int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) - { - if (getPacketType(inBuffer) == PKT_BLOCK_PART) - { + if (ret > 1) { + if (getPacketType(inBuffer) == PKT_BLOCK_PART) { struct blockPart *bp = (struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1); success = processBlockPart(bp); } @@ -327,25 +283,20 @@ static bool blockRxLoop(const uint32_t timeout) radioRxFlush(); return success; } -static struct blockRequestAck *continueToRX() -{ +static struct blockRequestAck *continueToRX() { struct blockRequestAck *ack = (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1); ack->pleaseWaitMs = 0; return ack; } -static void sendBlockRequest() -{ +static void sendBlockRequest() { memset(outBuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct blockRequest) + 2 + 2); struct MacFrameNormal *f = (struct MacFrameNormal *)(outBuffer + 1); struct blockRequest *blockreq = (struct blockRequest *)(outBuffer + 2 + sizeof(struct MacFrameNormal)); outBuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockRequest) + 2 + 2; - if (requestPartialBlock) - { + if (requestPartialBlock) { ; outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PARTIAL_REQUEST; - } - else - { + } else { outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST; } memcpy(f->src, mSelfMac, 8); @@ -365,37 +316,32 @@ static void sendBlockRequest() addCRC(blockreq, sizeof(struct blockRequest)); commsTxNoCpy(outBuffer); } -static struct blockRequestAck *performBlockRequest() -{ +static struct blockRequestAck *performBlockRequest() { uint32_t t; radioRxEnable(true); radioRxFlush(); - for (uint8_t c = 0; c < 30; c++) - { + for (uint8_t c = 0; c < 30; c++) { sendBlockRequest(); t = timerGet() + (TIMER_TICKS_PER_MSEC * (7UL + c / 10)); - do - { + do { int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) - { - switch (getPacketType(inBuffer)) - { - case PKT_BLOCK_REQUEST_ACK: - if (checkCRC((inBuffer + sizeof(struct MacFrameNormal) + 1), sizeof(struct blockRequestAck))) - return (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1); - break; - case PKT_BLOCK_PART: - // block already started while we were waiting for a get block reply - // printf("!"); - // processBlockPart((struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1)); - return continueToRX(); - break; - case PKT_CANCEL_XFER: - return NULL; - default: - printf("pkt w/type %02X\n", getPacketType(inBuffer)); - break; + if (ret > 1) { + switch (getPacketType(inBuffer)) { + case PKT_BLOCK_REQUEST_ACK: + if (checkCRC((inBuffer + sizeof(struct MacFrameNormal) + 1), sizeof(struct blockRequestAck))) + return (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1); + break; + case PKT_BLOCK_PART: + // block already started while we were waiting for a get block reply + // printf("!"); + // processBlockPart((struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1)); + return continueToRX(); + break; + case PKT_CANCEL_XFER: + return NULL; + default: + printf("pkt w/type %02X\n", getPacketType(inBuffer)); + break; } } @@ -404,8 +350,7 @@ static struct blockRequestAck *performBlockRequest() return continueToRX(); // return NULL; } -static void sendXferCompletePacket() -{ +static void sendXferCompletePacket() { memset(outBuffer, 0, sizeof(struct MacFrameNormal) + 2 + 4); struct MacFrameNormal *f = (struct MacFrameNormal *)(outBuffer + 1); outBuffer[0] = sizeof(struct MacFrameNormal) + 2 + 2; @@ -424,21 +369,16 @@ static void sendXferCompletePacket() f->seq = seq++; commsTxNoCpy(outBuffer); } -static void sendXferComplete() -{ +static void sendXferComplete() { radioRxEnable(true); - for (uint8_t c = 0; c < 16; c++) - { + for (uint8_t c = 0; c < 16; c++) { sendXferCompletePacket(); uint32_t start = timerGet(); - while ((timerGet() - start) < (TIMER_TICKS_PER_MSEC * 6UL)) - { + while ((timerGet() - start) < (TIMER_TICKS_PER_MSEC * 6UL)) { int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) - { - if (getPacketType(inBuffer) == PKT_XFER_COMPLETE_ACK) - { + if (ret > 1) { + if (getPacketType(inBuffer) == PKT_XFER_COMPLETE_ACK) { printf("XFC ACK\n"); return; } @@ -448,25 +388,21 @@ static void sendXferComplete() printf("XFC NACK!\n"); return; } -static bool validateBlockData() -{ +static bool validateBlockData() { struct blockData *bd = (struct blockData *)blockXferBuffer; // printf("expected len = %04X, checksum=%04X\n", bd->size, bd->checksum); uint16_t t = 0; - for (uint16_t c = 0; c < bd->size; c++) - { + for (uint16_t c = 0; c < bd->size; c++) { t += bd->data[c]; } return bd->checksum == t; } // EEprom related stuff -static uint32_t getAddressForSlot(const uint8_t s) -{ +static uint32_t getAddressForSlot(const uint8_t s) { return EEPROM_IMG_START + (EEPROM_IMG_EACH * s); } -static void getNumSlots() -{ +static void getNumSlots() { printf("Checking slots\n"); imgSlots = 1; @@ -487,40 +423,29 @@ static void getNumSlots() imgSlots = nSlots;*/ printf("Got %i nr of slots\n", imgSlots); } -static uint8_t findSlot(const uint8_t *ver) -{ +static uint8_t findSlot(const uint8_t *ver) { // return 0xFF; // remove me! This forces the tag to re-download each and every upload without checking if it's already in the eeprom somewhere uint32_t markerValid = EEPROM_IMG_VALID; - for (uint8_t c = 0; c < imgSlots; c++) - { + for (uint8_t c = 0; c < imgSlots; c++) { struct EepromImageHeader *eih = (struct EepromImageHeader *)blockXferBuffer; eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader)); - if (!memcmp(&eih->validMarker, &markerValid, 4)) - { - if (!memcmp(&eih->version, (void *)ver, 8)) - { + if (!memcmp(&eih->validMarker, &markerValid, 4)) { + if (!memcmp(&eih->version, (void *)ver, 8)) { return c; } } } return 0xFF; } -static void eraseUpdateBlock() -{ - eepromErase(EEPROM_UPDATA_AREA_START, EEPROM_UPDATE_AREA_LEN); +static void eraseUpdateBlock() { + eepromErase(EEPROM_UPDATA_AREA_START, (uint16_t)EEPROM_UPDATE_AREA_LEN); } -static void eraseImageBlock(const uint8_t c) -{ - eepromErase(getAddressForSlot(c), EEPROM_IMG_EACH); -} -static void saveUpdateBlockData(uint8_t blockId) -{ +static void saveUpdateBlockData(uint8_t blockId) { printf("EEPROM writing UpdateBlock %i\n", blockId); if (!eepromWrite(EEPROM_UPDATA_AREA_START + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), BLOCK_DATA_SIZE)) printf("EEPROM write failed\n"); } -static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId) -{ +static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId) { printf("EEPROM writing Slot: %i ImageBlock %i\n", imgSlot, blockId); uint32_t length = EEPROM_IMG_EACH - (sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE)); if (length > 4096) @@ -529,13 +454,11 @@ static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId) if (!eepromWrite(getAddressForSlot(imgSlot) + sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), length)) printf("EEPROM write failed\n"); } -void drawImageFromEeprom(const uint8_t imgSlot) -{ +void drawImageFromEeprom(const uint8_t imgSlot) { drawImageAtAddress(getAddressForSlot(imgSlot), drawWithLut); - drawWithLut = 0; // default back to the regular ol' stock/OTP LUT + drawWithLut = 0; // default back to the regular ol' stock/OTP LUT } -static uint32_t getHighSlotId() -{ +static uint32_t getHighSlotId() { uint32_t temp = 0; /*uint32_t markerValid = EEPROM_IMG_VALID; for (uint8_t c = 0; c < imgSlots; c++) @@ -556,47 +479,37 @@ static uint32_t getHighSlotId() } static uint8_t partsThisBlock = 0; -static uint8_t blockAttempts = 0; // these CAN be local to the function, but for some reason, they won't survive sleep? - // they get overwritten with 7F 32 44 20 00 00 00 00 11, I don't know why. +static uint8_t blockAttempts = 0; // these CAN be local to the function, but for some reason, they won't survive sleep? + // they get overwritten with 7F 32 44 20 00 00 00 00 11, I don't know why. -static bool getDataBlock(const uint16_t blockSize) -{ +static bool getDataBlock(const uint16_t blockSize) { blockAttempts = BLOCK_TRANSFER_ATTEMPTS; - if (blockSize == BLOCK_DATA_SIZE) - { + if (blockSize == BLOCK_DATA_SIZE) { partsThisBlock = BLOCK_MAX_PARTS; memset(curBlock.requestedParts, 0xFF, BLOCK_REQ_PARTS_BYTES); - } - else - { + } else { partsThisBlock = (sizeof(struct blockData) + blockSize) / BLOCK_PART_DATA_SIZE; if (blockSize % BLOCK_PART_DATA_SIZE) partsThisBlock++; memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES); - for (uint8_t c = 0; c < partsThisBlock; c++) - { + for (uint8_t c = 0; c < partsThisBlock; c++) { curBlock.requestedParts[c / 8] |= (1 << (c % 8)); } } - requestPartialBlock = false; // this forces the AP to request the block data from the host + requestPartialBlock = false; // this forces the AP to request the block data from the host - while (blockAttempts--) - { + while (blockAttempts--) { #ifndef DEBUGBLOCKS printf("REQ %d ", curBlock.blockId); #else printf("REQ %d[", curBlock.blockId); - for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) - { + for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) { if ((c != 0) && (c % 8 == 0)) printf("]["); - if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) - { + if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) { printf("R"); - } - else - { + } else { printf("_"); } } @@ -605,34 +518,26 @@ static bool getDataBlock(const uint16_t blockSize) powerUp(INIT_RADIO); struct blockRequestAck *ack = performBlockRequest(); - if (ack == NULL) - { + if (ack == NULL) { printf("Cancelled request\n"); return false; } - if (ack->pleaseWaitMs) - { // SLEEP - until the AP is ready with the data + if (ack->pleaseWaitMs) { // SLEEP - until the AP is ready with the data timerDelay(TIMER_TICKS_PER_MSEC * ack->pleaseWaitMs); - } - else - { + } else { // immediately start with the reception of the block data } - blockRxLoop(270); // BLOCK RX LOOP - receive a block, until the timeout has passed + blockRxLoop(270); // BLOCK RX LOOP - receive a block, until the timeout has passed powerDown(INIT_RADIO); #ifdef DEBUGBLOCKS printf("RX %d[", curBlock.blockId); - for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) - { + for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) { if ((c != 0) && (c % 8 == 0)) printf("]["); - if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) - { + if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) { printf("."); - } - else - { + } else { printf("R"); } } @@ -640,34 +545,26 @@ static bool getDataBlock(const uint16_t blockSize) #endif // check if we got all the parts we needed, e.g: has the block been completed? bool blockComplete = true; - for (uint8_t c = 0; c < partsThisBlock; c++) - { + for (uint8_t c = 0; c < partsThisBlock; c++) { if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) blockComplete = false; } - if (blockComplete) - { + if (blockComplete) { #ifndef DEBUGBLOCKS printf("- COMPLETE\n"); #endif - if (validateBlockData()) - { + if (validateBlockData()) { // block download complete, validated return true; - } - else - { - for (uint8_t c = 0; c < partsThisBlock; c++) - { + } else { + for (uint8_t c = 0; c < partsThisBlock; c++) { curBlock.requestedParts[c / 8] |= (1 << (c % 8)); } requestPartialBlock = false; printf("blk failed validation!\n"); } - } - else - { + } else { #ifndef DEBUGBLOCKS printf("- INCOMPLETE\n"); #endif @@ -679,15 +576,11 @@ static bool getDataBlock(const uint16_t blockSize) return false; } uint16_t dataRequestSize = 0; -static bool downloadFWUpdate(const struct AvailDataInfo *avail) -{ +static bool downloadFWUpdate(const struct AvailDataInfo *avail) { // check if we already started the transfer of this information & haven't completed it - if (!memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8) && curDataInfo.dataSize) - { + if (!memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8) && curDataInfo.dataSize) { // looks like we did. We'll carry on where we left off. - } - else - { + } else { // start, or restart the transfer from 0. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer curBlock.blockId = 0; memcpy(&(curBlock.ver), &(avail->dataVer), 8); @@ -696,30 +589,23 @@ static bool downloadFWUpdate(const struct AvailDataInfo *avail) eraseUpdateBlock(); } - while (curDataInfo.dataSize) - { + while (curDataInfo.dataSize) { wdt10s(); - if (curDataInfo.dataSize > BLOCK_DATA_SIZE) - { + if (curDataInfo.dataSize > BLOCK_DATA_SIZE) { // more than one block remaining dataRequestSize = BLOCK_DATA_SIZE; - } - else - { + } else { // only one block remains dataRequestSize = curDataInfo.dataSize; } - if (getDataBlock(dataRequestSize)) - { + if (getDataBlock(dataRequestSize)) { // succesfully downloaded datablock, save to eeprom powerUp(INIT_EEPROM); saveUpdateBlockData(curBlock.blockId); powerDown(INIT_EEPROM); curBlock.blockId++; curDataInfo.dataSize -= dataRequestSize; - } - else - { + } else { // failed to get the block we wanted, we'll stop for now, maybe resume later return false; } @@ -729,17 +615,13 @@ static bool downloadFWUpdate(const struct AvailDataInfo *avail) } uint16_t imageSize = 0; -static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) -{ +static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) { // check if we already started the transfer of this information & haven't completed it - if (!memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8) && curDataInfo.dataSize) - { + if (!memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8) && curDataInfo.dataSize) { // looks like we did. We'll carry on where we left off. printf("restarting image download"); curImgSlot = nextImgSlot; - } - else - { + } else { // go to the next image slot nextImgSlot++; if (nextImgSlot >= imgSlots) @@ -749,17 +631,10 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) drawWithLut = avail->dataTypeArgument; powerUp(INIT_EEPROM); uint8_t attempt = 5; - while (attempt--) - { - if (eepromErase(getAddressForSlot(curImgSlot), EEPROM_IMG_EACH)) + while (attempt--) { + if (eepromErase(getAddressForSlot(curImgSlot), (uint16_t)EEPROM_IMG_EACH)) goto eraseSuccess; } - eepromFail: - powerDown(INIT_RADIO); - powerUp(INIT_EPD); - uiPrvFullscreenMsg("No EEPROM :(", NULL, NULL); - powerDown(INIT_EEPROM | INIT_EPD); - doSleep(-1); NVIC_SystemReset(); eraseSuccess: printf("new download, writing to slot %d\n", curImgSlot); @@ -768,25 +643,22 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) curBlock.blockId = 0; memcpy(&(curBlock.ver), &(avail->dataVer), 8); curBlock.type = avail->dataType; + memcpy(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); + imageSize = curDataInfo.dataSize; } - while (curDataInfo.dataSize) - { + while (curDataInfo.dataSize) { wdt10s(); - if (curDataInfo.dataSize > BLOCK_DATA_SIZE) - { + if (curDataInfo.dataSize > BLOCK_DATA_SIZE) { // more than one block remaining dataRequestSize = BLOCK_DATA_SIZE; - } - else - { + } else { // only one block remains dataRequestSize = curDataInfo.dataSize; } - if (getDataBlock(dataRequestSize)) - { + if (getDataBlock(dataRequestSize)) { // succesfully downloaded datablock, save to eeprom powerUp(INIT_EEPROM); #ifdef DEBUGBLOCKS @@ -796,9 +668,7 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) powerDown(INIT_EEPROM); curBlock.blockId++; curDataInfo.dataSize -= dataRequestSize; - } - else - { + } else { // failed to get the block we wanted, we'll stop for now, probably resume later return false; } @@ -823,112 +693,98 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) return true; } -bool processAvailDataInfo(struct AvailDataInfo *avail) -{ - switch (avail->dataType) - { - case DATATYPE_IMG_BMP: - case DATATYPE_IMG_DIFF: - case DATATYPE_IMG_RAW_1BPP: - case DATATYPE_IMG_RAW_2BPP: - // check if this download is currently displayed or active - if (curDataInfo.dataSize == 0 && !memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8)) - { - // we've downloaded this already, we're guessing it's already displayed - printf("currently shown image, send xfc\n"); - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - return true; - } +bool processAvailDataInfo(struct AvailDataInfo *avail) { + switch (avail->dataType) { + case DATATYPE_IMG_BMP: + case DATATYPE_IMG_DIFF: + case DATATYPE_IMG_RAW_1BPP: + case DATATYPE_IMG_RAW_2BPP: + // check if this download is currently displayed or active + if (curDataInfo.dataSize == 0 && !memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8)) { + // we've downloaded this already, we're guessing it's already displayed + printf("currently shown image, send xfc\n"); + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + return true; + } - // check if we've seen this version before - powerUp(INIT_EEPROM); - curImgSlot = findSlot((uint8_t *)&(avail->dataVer)); - powerDown(INIT_EEPROM); - if (curImgSlot != 0xFF) - { - // found a (complete)valid image slot for this version - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - - printf("already seen, drawing from eeprom slot %d\n", curImgSlot); - - // mark as completed and draw from EEPROM - memcpy(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); - curDataInfo.dataSize = 0; // mark as transfer not pending - - drawWithLut = avail->dataTypeArgument; - wdt60s(); - powerUp(INIT_EPD | INIT_EEPROM); - drawImageFromEeprom(curImgSlot); - powerDown(INIT_EPD | INIT_EEPROM); - return true; - } - else - { - // not found in cache, prepare to download - printf("downloading to imgslot\n"); - drawWithLut = avail->dataTypeArgument; + // check if we've seen this version before powerUp(INIT_EEPROM); - if (downloadImageDataToEEPROM(avail)) - { - printf("download complete!\n"); + curImgSlot = findSlot((uint8_t *)&(avail->dataVer)); + powerDown(INIT_EEPROM); + if (curImgSlot != 0xFF) { + // found a (complete)valid image slot for this version powerUp(INIT_RADIO); sendXferComplete(); powerDown(INIT_RADIO); + printf("already seen, drawing from eeprom slot %d\n", curImgSlot); + + // mark as completed and draw from EEPROM + memcpy(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); + curDataInfo.dataSize = 0; // mark as transfer not pending + + drawWithLut = avail->dataTypeArgument; wdt60s(); powerUp(INIT_EPD | INIT_EEPROM); drawImageFromEeprom(curImgSlot); powerDown(INIT_EPD | INIT_EEPROM); return true; + } else { + // not found in cache, prepare to download + printf("downloading to imgslot\n"); + drawWithLut = avail->dataTypeArgument; + powerUp(INIT_EEPROM); + if (downloadImageDataToEEPROM(avail)) { + printf("download complete!\n"); + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + + wdt60s(); + powerUp(INIT_EPD | INIT_EEPROM); + drawImageFromEeprom(curImgSlot); + powerDown(INIT_EPD | INIT_EEPROM); + return true; + } else { + powerDown(INIT_EEPROM); + return false; + } } - else - { - powerDown(INIT_EEPROM); + break; + case DATATYPE_FW_UPDATE: + powerUp(INIT_EEPROM); + if (downloadFWUpdate(avail)) { + printf("firmware download complete, doing update.\n"); + + powerUp(INIT_EPD); + // uiPrvFullscreenMsg("Updating", NULL, NULL); + + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + + powerUp(INIT_EEPROM); + wdt60s(); + prvApplyUpdateIfNeeded(); + } else { return false; } - } - break; - case DATATYPE_FW_UPDATE: - powerUp(INIT_EEPROM); - if (downloadFWUpdate(avail)) - { - printf("firmware download complete, doing update.\n"); - - powerUp(INIT_EPD); - uiPrvFullscreenMsg("Updating", NULL, NULL); - - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - - powerUp(INIT_EEPROM); - wdt60s(); - prvApplyUpdateIfNeeded(); - } - else - { + break; + case DATATYPE_NFC_URL_DIRECT: + case DATATYPE_NFC_RAW_CONTENT: { return false; + break; } - break; - case DATATYPE_NFC_URL_DIRECT: - case DATATYPE_NFC_RAW_CONTENT: - { - return false; - break; - } - case DATATYPE_CUSTOM_LUT_OTA: - return false; - break; + case DATATYPE_CUSTOM_LUT_OTA: + return false; + break; } return true; } -void initializeProto() -{ +void initializeProto() { getNumSlots(); curHighSlotId = getHighSlotId(); } \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.h index 0066fa73..f0eafddc 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.h @@ -1,14 +1,19 @@ #pragma once -#include #include +#include + #include "settings.h" -extern uint8_t mSelfMac[]; -extern uint8_t currentChannel; +extern __attribute__((section(".aonshadow"))) uint8_t mSelfMac[]; +extern __attribute__((section(".aonshadow"))) volatile uint8_t currentChannel; +extern __attribute__((section(".aonshadow"))) struct blockRequest curBlock; // used by the block-requester, contains the next request that we'll send +extern __attribute__((section(".aonshadow"))) struct AvailDataInfo curDataInfo; // last 'AvailDataInfo' we received from the AP // __attribute__((section(".aon"))) + + extern uint8_t APmac[]; -extern uint8_t curImgSlot; +extern __attribute__((section(".aonshadow"))) uint8_t curImgSlot; extern void setupRadio(void); extern void killRadio(void); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.c new file mode 100644 index 00000000..fc674ab1 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.c @@ -0,0 +1,181 @@ +#include "userinterface.h" + +#include +#include + +#include "bitmaps.h" +#include "board.h" +#include "comms.h" +#include "epd.h" +#include "font.h" +#include "powermgt.h" +#include "printf.h" +#include "proto.h" +#include "screen.h" +#include "settings.h" +#include "syncedproto.h" // for APmac / Channel +#include "timer.h" + +const uint16_t fwVersion = FW_VERSION; +const char fwVersionSuffix[] = FW_VERSION_SUFFIX; + +extern uint8_t capabilities; + +bool __attribute__((section(".aonshadow"))) lowBatteryShown = false; +bool __attribute__((section(".aonshadow"))) noAPShown = false; + +void addCapabilities() { + // if (capabilities) epdpr("Options: "); + if (capabilities & CAPABILITY_HAS_NFC) { + // epdpr("-NFC"); + if (capabilities & CAPABILITY_NFC_WAKE) { + // epdpr("+WAKE"); + } else { + // epdpr(" "); + } + } + if (capabilities & CAPABILITY_HAS_WAKE_BUTTON) { + // epdpr("-WAKE BUTTON"); + } +} + +void addOverlay() { + if ((currentChannel == 0) && (tagSettings.enableNoRFSymbol)) { + // loadRawBitmap(ant, SCREEN_WIDTH - 24, 6, EPD_COLOR_BLACK); + // loadRawBitmap(cross, SCREEN_WIDTH - 16, 13, EPD_COLOR_RED); + noAPShown = true; + } else { + noAPShown = false; + } + if ((batteryVoltage < tagSettings.batLowVoltage) && (tagSettings.enableLowBatSymbol)) { + // loadRawBitmap(battery, SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, EPD_COLOR_BLACK); + lowBatteryShown = true; + } else { + lowBatteryShown = false; + } +} + +void afterFlashScreenSaver() { + // selectLUT(EPD_LUT_DEFAULT); + // clearScreen(); + +#if (SCREEN_WIDTH == 400) // 4.2" + epdPrintBegin(3, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("OpenEPaperLink"); + epdPrintEnd(); +#endif + // drawWithSleep(); +} + +void showSplashScreen() { + // selectLUT(EPD_LUT_NO_REPEATS); + // clearScreen(); +#if (SCREEN_WIDTH == 400) // 4.2" + epdPrintBegin(3, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("Starting"); + epdPrintEnd(); + + epdPrintBegin(2, 252, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + addCapabilities(); + epdPrintEnd(); + + epdPrintBegin(3, 268, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("zbs42v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix); + epdPrintEnd(); + epdPrintBegin(3, 284, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED); + epdpr("MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]); + epdpr(":%02X:%02X", mSelfMac[5], mSelfMac[4]); + epdpr(":%02X:%02X", mSelfMac[3], mSelfMac[2]); + epdpr(":%02X:%02X", mSelfMac[1], mSelfMac[0]); + epdPrintEnd(); + + loadRawBitmap(oepli, 136, 22, EPD_COLOR_BLACK); + loadRawBitmap(cloud, 136, 10, EPD_COLOR_RED); + + uint8_t __xdata buffer[17]; + spr(buffer, "%02X%02X", mSelfMac[7], mSelfMac[6]); + spr(buffer + 4, "%02X%02X", mSelfMac[5], mSelfMac[4]); + spr(buffer + 8, "%02X%02X", mSelfMac[3], mSelfMac[2]); + spr(buffer + 12, "%02X%02X", mSelfMac[1], mSelfMac[0]); + printBarcode(buffer, 392, 264); + printBarcode(buffer, 384, 264); + +#endif + // drawWithSleep(); +} + +void showApplyUpdate() { + // selectLUT(1); + // clearScreen(); +#if (SCREEN_WIDTH == 400) + epdPrintBegin(136, 134, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); +#endif + + // epdpr("Updating!"); + // epdPrintEnd(); + // drawNoWait(); +} + +void showAPFound() { + + init_epd(); + fillWindow(0, 0, 640, 384, 1); + epdPrintf(10, 10, 1, "OpenEPaperLink"); + epdPrintf(10, 40, 1, "AP Found at channel %d", currentChannel); + epdPrintf(10, 60, 1, "AP MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", APmac[7], APmac[6], APmac[5], APmac[4], APmac[3], APmac[2], APmac[1], APmac[0]); + + epdPrintf(10, 330, 1, "Battery: %d.%dV", batteryVoltage / 1000, batteryVoltage % 1000); + epdPrintf(10, 350, 1, "Tag MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]); + epd_refresh_and_sleep(); +} + +void showNoAP() { + init_epd(); + fillWindow(0, 0, 640, 384, 1); + epdPrintf(10, 10, 1, "OpenEPaperLink "); + epdPrintf(10, 40, 1, "No AP found... We'll try again in a little while though!"); + epdPrintf(10, 350, 1, "Tag MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]); + + epd_refresh_and_sleep(); +} + +void showLongTermSleep() { + // selectLUT(EPD_LUT_NO_REPEATS); + // clearScreen(); + + // epdPrintBegin(2, SCREEN_HEIGHT - 16, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + // epdpr("zZ"); + // epdPrintEnd(); + + addOverlay(); + // drawWithSleep(); +} +void showNoEEPROM() { + // selectLUT(EPD_LUT_NO_REPEATS); + // clearScreen(); +#if (SCREEN_WIDTH == 400) // 4.2" + epdPrintBegin(50, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("EEPROM FAILED :("); + epdPrintEnd(); + loadRawBitmap(failed, 176, 126, EPD_COLOR_RED); + epdPrintBegin(100, 284, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("Sleeping forever :'("); + epdPrintEnd(); +#endif + // drawWithSleep(); +} + +void showNoMAC() { + // selectLUT(EPD_LUT_NO_REPEATS); + // clearScreen(); +#if (SCREEN_WIDTH == 400) // 4.2" + epdPrintBegin(100, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("NO MAC SET :("); + epdPrintEnd(); + loadRawBitmap(failed, 176, 126, EPD_COLOR_RED); + epdPrintBegin(100, 284, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("Sleeping forever :'("); + epdPrintEnd(); +#endif + // drawWithSleep(); +} \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.h new file mode 100644 index 00000000..d9d69079 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.h @@ -0,0 +1,22 @@ +#ifndef _UI_H_ +#define _UI_H_ +#include +#include + +void addOverlay(); + +void afterFlashScreenSaver(); +void showSplashScreen(); +void showApplyUpdate(); +void showAPFound(); +void showNoAP(); +void showLongTermSleep(); +void showNoEEPROM(); +void showNoMAC(); + +extern const uint16_t fwVersion; +extern const char fwVersionSuffix[]; +extern __attribute__((section(".aon"))) bool lowBatteryShown; +extern __attribute__((section(".aon"))) bool noAPShown; + +#endif \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/util.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/util.c index 86503a53..e17bdc90 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/util.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/util.c @@ -1,213 +1,185 @@ -#include -#include -#include "eeprom.h" -#include "timer.h" -#include "mz100.h" #include "util.h" -#include "mz100_flash.h" + +#include +//#include +#include "printf.h" + +#include "eeprom.h" +#include "mz100.h" #include "mz100_adc.h" +#include "mz100_flash.h" #include "mz100_wdt.h" +#include "timer.h" -void wdt10s() -{ +void wdt10s() { WDT_RestartCounter(); } -void wdt30s() -{ +void wdt30s() { WDT_RestartCounter(); } -void wdt60s() -{ +void wdt60s() { WDT_RestartCounter(); } -void delay(int cnt) -{ - volatile unsigned int i; - for (i = 107 * cnt; i; --i) - ; +void delay(int cnt) { + volatile unsigned int i; + for (i = 107 * cnt; i; --i) + ; } -void delay_us(unsigned int result) -{ - volatile unsigned int i; +void delay_us(unsigned int result) { + volatile unsigned int i; - for (i = 0; i < result; ++i) - ; + for (i = 0; i < result; ++i) + ; } -uint16_t crc16(uint16_t cur_crc, uint8_t data) -{ - cur_crc ^= data; - for (uint8_t i = 8; i > 0; i--) - { - if ((cur_crc & 0x001) != 0) - { - cur_crc >>= 1; - cur_crc ^= 0x8005; // poly - } - else - { - cur_crc >>= 1; - } - } - return cur_crc; +uint16_t crc16(uint16_t cur_crc, uint8_t data) { + cur_crc ^= data; + for (uint8_t i = 8; i > 0; i--) { + if ((cur_crc & 0x001) != 0) { + cur_crc >>= 1; + cur_crc ^= 0x8005; // poly + } else { + cur_crc >>= 1; + } + } + return cur_crc; } -uint32_t measureTemp(void) -{ - uint32_t result = 0; - ADC_CFG_Type adc_config; - adc_config.adcResolution = ADC_RESOLUTION_14BIT; - adc_config.adcVrefSource = ADC_VREF_INTERNAL; // 1.2V - adc_config.adcGainSel = ADC_GAIN_1; - adc_config.adcClockDivider = ADC_CLOCK_DIVIDER_4; - adc_config.adcBiasMode = ADC_BIAS_FULL; +uint32_t measureTemp(void) { + uint32_t result = 0; + ADC_CFG_Type adc_config; + adc_config.adcResolution = ADC_RESOLUTION_14BIT; + adc_config.adcVrefSource = ADC_VREF_INTERNAL; // 1.2V + adc_config.adcGainSel = ADC_GAIN_1; + adc_config.adcClockDivider = ADC_CLOCK_DIVIDER_4; + adc_config.adcBiasMode = ADC_BIAS_FULL; - ADC_Reset(); - ADC_ModeSelect(ADC_MODE_TSENSOR); - ADC_TSensorConfig(ADC_TEMPP, ADC_SENSOR_INTERNAL); - ADC_Init(&adc_config); - ADC_Enable(); - for (int i = 0; i < 32; i++) - { - ADC_ConversionStart(); - ADC_IntClr(ADC_RDY); - while (!ADC_GetStatus(ADC_STATUS_RDY)) - ; - ADC_ConversionStop(); - } - for (int i = 0; i < 128; i++) - { - ADC_ConversionStart(); - ADC_IntClr(ADC_RDY); - while (!ADC_GetStatus(ADC_STATUS_RDY)) - ; - ADC_ConversionStop(); - result += (ADC_GetConversionResult() - 458) / 1.7; - } - result /= 128; - printf("Temp: %iC\r\n", result); - return result; + ADC_Reset(); + ADC_ModeSelect(ADC_MODE_TSENSOR); + ADC_TSensorConfig(ADC_TEMPP, ADC_SENSOR_INTERNAL); + ADC_Init(&adc_config); + ADC_Enable(); + for (int i = 0; i < 32; i++) { + ADC_ConversionStart(); + ADC_IntClr(ADC_RDY); + while (!ADC_GetStatus(ADC_STATUS_RDY)) + ; + ADC_ConversionStop(); + } + for (int i = 0; i < 128; i++) { + ADC_ConversionStart(); + ADC_IntClr(ADC_RDY); + while (!ADC_GetStatus(ADC_STATUS_RDY)) + ; + ADC_ConversionStop(); + result += (ADC_GetConversionResult() - 458) / 1.7; + } + result /= 128; + printf("Temp: %iC\r\n", result); + return result; } -uint32_t measureBattery(void) -{ - uint32_t result = 0; - ADC_CFG_Type adc_config; - adc_config.adcResolution = ADC_RESOLUTION_16BIT; - adc_config.adcVrefSource = ADC_VREF_VCAU; // 1.8V - adc_config.adcGainSel = ADC_GAIN_1; // range 0 - 1.8V - adc_config.adcClockDivider = ADC_CLOCK_DIVIDER_4; - adc_config.adcBiasMode = ADC_BIAS_FULL; +uint32_t measureBattery(void) { + uint32_t result = 0; + ADC_CFG_Type adc_config; + adc_config.adcResolution = ADC_RESOLUTION_16BIT; + adc_config.adcVrefSource = ADC_VREF_VCAU; // 1.8V + adc_config.adcGainSel = ADC_GAIN_1; // range 0 - 1.8V + adc_config.adcClockDivider = ADC_CLOCK_DIVIDER_4; + adc_config.adcBiasMode = ADC_BIAS_FULL; - ADC_Reset(); - ADC_ModeSelect(ADC_MODE_ADC); - ADC_ChannelConfig(ADC_VBATS); // 0.33 of Actual Voltage - ADC_Init(&adc_config); - ADC_Enable(); - ADC_ConversionStart(); - ADC_IntClr(ADC_RDY); - for (int i = 0; i < 32; i++) - { - ADC_ConversionStart(); - ADC_IntClr(ADC_RDY); - while (!ADC_GetStatus(ADC_STATUS_RDY)) - ; - ADC_ConversionStop(); - } - for (int i = 0; i < 128; i++) - { - ADC_ConversionStart(); - ADC_IntClr(ADC_RDY); - while (!ADC_GetStatus(ADC_STATUS_RDY)) - ; - ADC_ConversionStop(); - result += ADC_GetConversionResult() * 5940 / 32768; - } - result /= 128; - printf("Voltage: %imV\r\n", result); - return result; + ADC_Reset(); + ADC_ModeSelect(ADC_MODE_ADC); + ADC_ChannelConfig(ADC_VBATS); // 0.33 of Actual Voltage + ADC_Init(&adc_config); + ADC_Enable(); + ADC_ConversionStart(); + ADC_IntClr(ADC_RDY); + for (int i = 0; i < 32; i++) { + ADC_ConversionStart(); + ADC_IntClr(ADC_RDY); + while (!ADC_GetStatus(ADC_STATUS_RDY)) + ; + ADC_ConversionStop(); + } + for (int i = 0; i < 128; i++) { + ADC_ConversionStart(); + ADC_IntClr(ADC_RDY); + while (!ADC_GetStatus(ADC_STATUS_RDY)) + ; + ADC_ConversionStop(); + result += ADC_GetConversionResult() * 5940 / 32768; + } + result /= 128; + printf("Voltage: %imV\r\n", result); + return result; } -void qspiEraseRange(uint32_t addr, uint32_t len) -{ - uint64_t time; - // round starting address down - if (addr % EEPROM_PAGE_SIZE) - { - len += addr % EEPROM_PAGE_SIZE; - addr = addr / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE; - } +void qspiEraseRange(uint32_t addr, uint32_t len) { + uint64_t time; + // round starting address down + if (addr % EEPROM_PAGE_SIZE) { + len += addr % EEPROM_PAGE_SIZE; + addr = addr / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE; + } - // round length up - len = (len + EEPROM_PAGE_SIZE - 1) / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE; + // round length up + len = (len + EEPROM_PAGE_SIZE - 1) / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE; - while (len) - { + while (len) { + uint32_t now; + bool ok; - uint32_t now; - bool ok; + WDT_RestartCounter(); + if (!(addr % 0x10000) && len >= 0x10000) { + ok = FLASH_Block64KErase(addr / 0x10000); + now = 0x10000; + } else if (!(addr % 0x8000) && len >= 0x8000) { + ok = FLASH_Block32KErase(addr / 0x8000); + now = 0x8000; + } else { + ok = FLASH_SectorErase(addr / 0x1000); + now = 0x1000; + } - WDT_RestartCounter(); - if (!(addr % 0x10000) && len >= 0x10000) - { - ok = FLASH_Block64KErase(addr / 0x10000); - now = 0x10000; - } - else if (!(addr % 0x8000) && len >= 0x8000) - { - ok = FLASH_Block32KErase(addr / 0x8000); - now = 0x8000; - } - else - { - ok = FLASH_SectorErase(addr / 0x1000); - now = 0x1000; - } + if (!ok) + printf("ERZ fail at 0x%08x + %u\r\n", addr, now); - if (!ok) - printf("ERZ fail at 0x%08x + %u\r\n", addr, now); - - addr += now; - len -= now; - if (len) - { - // let the caps recharge - time = timerGet(); - while (timerGet() - time < TIMER_TICKS_PER_SEC / 10) - ; - } - } - WDT_RestartCounter(); + addr += now; + len -= now; + if (len) { + // let the caps recharge + time = timerGet(); + while (timerGet() - time < TIMER_TICKS_PER_SEC / 10) + ; + } + } + WDT_RestartCounter(); } -bool eepromWrite(uint32_t addr, const void *srcP, uint16_t len) -{ - FLASH_Write(false, addr, srcP, len); - return true; +bool eepromWrite(uint32_t addr, const void *srcP, uint16_t len) { + FLASH_Write(false, addr, (void*)srcP, len); + return true; } -bool eepromErase(uint32_t addr, uint16_t nSec) -{ - qspiEraseRange(addr, nSec); - return true; +bool eepromErase(uint32_t addr, uint16_t nSec) { + qspiEraseRange(addr, nSec); + return true; } -void eepromRead(uint32_t addr, void *dstP, uint16_t len) -{ - uint8_t *dst = (uint8_t *)dstP; - FLASH_Read(0, addr, dst, len); +void eepromRead(uint32_t addr, void *dstP, uint16_t len) { + uint8_t *dst = (uint8_t *)dstP; + FLASH_Read(0, addr, dst, len); } -uint32_t eepromGetSize(void) -{ - return EEPROM_IMG_LEN; +uint32_t eepromGetSize(void) { + return EEPROM_IMG_LEN; } -void radioShutdown(void) -{ - // i have no idea what these do, determined by writing random registers and watching the current drawn - *(volatile uint32_t *)0x4C000000 = 0; - *(volatile uint32_t *)0x4C010000 = 0; - *(volatile uint32_t *)0x4C010004 = 0x10000000; +void radioShutdown(void) { + // i have no idea what these do, determined by writing random registers and watching the current drawn + *(volatile uint32_t *)0x4C000000 = 0; + *(volatile uint32_t *)0x4C010000 = 0; + *(volatile uint32_t *)0x4C010004 = 0x10000000; } \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/zigbee.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/zigbee.c index 18410137..59f5b80b 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/zigbee.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/zigbee.c @@ -1,7 +1,8 @@ -#include +//#include #include #include "util.h" #include "zigbee.h" +#include "printf.h" volatile uint8_t calibration_irq_ocoured = 0; volatile uint8_t zigbee_tx_done = 0; @@ -145,24 +146,29 @@ void fill_rx_regs() ; } -void sub_1021E6() +void load_calib() { int v0; unsigned int v1; unsigned int i; v0 = (*(volatile unsigned int *)0x4C01000C); - v1 = get_register(0x130004); + v1 = zigbeeCalibData.len; (*(volatile unsigned int *)0x4C010000) |= 4u; while (((*(volatile unsigned int *)0x4C010008) & 0x1000000) == 0) ; for (i = 0; i < v1; ++i) - set_register(v0 + 4 * i + 0x4C014000, *(uint32_t *)(4 * i + 0x130008)); + set_register(v0 + 4 * i + 0x4C014000, zigbeeCalibData.data[i]); (*(volatile unsigned int *)0x4C010000) &= ~4u; while (((*(volatile unsigned int *)0x4C010008) & 0x1000000) != 0) ; } + + +// It is from 0x130000 up to 0x1301000 But you can only use 0x130404 up to the 0x1301000 + + void save_calib_in_ram() { int v0; @@ -171,14 +177,14 @@ void save_calib_in_ram() v0 = (*(volatile unsigned int *)0x4C01000C) + 0x4C014000; v1 = ((unsigned int)(uint8_t)((*(volatile unsigned int *)0x4C010008) >> 2) + 3) >> 2; - set_register(0x130000u, 0x464C4147); - set_register(0x130004u, v1); + zigbeeCalibData.isValid = true; (*(volatile unsigned int *)0x4C01001C) = -5; (*(volatile unsigned int *)0x4C010000) |= 2u; while (((*(volatile unsigned int *)0x4C010008) & 0x1000000) == 0) ; - for (i = 0; i < v1; ++i) - set_register(4 * i + 0x130008, *(uint32_t *)(v0 + 4 * i)); + for (i = 0; i < v1; ++i){ + zigbeeCalibData.data[i] = *(uint32_t *)(v0 + 4 * i); + } (*(volatile unsigned int *)0x4C010000) &= ~2u; while (((*(volatile unsigned int *)0x4C010008) & 0x1000000) != 0) ; @@ -189,12 +195,12 @@ int inner_calibration() int is_in_ram; (*(volatile unsigned int *)0x4C010000) |= 0x20u; - if (get_register(0x130000) == 0x464C4147) + if(zigbeeCalibData.isValid) { is_in_ram = 1; (*(volatile unsigned int *)0x4C010000) |= 8u; (*(volatile unsigned int *)0x4C010000) &= ~0x10u; - sub_1021E6(); + load_calib(); } else { diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/zigbee.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/zigbee.h index eeb50011..7dae8ac2 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/zigbee.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/zigbee.h @@ -1,4 +1,5 @@ #pragma once +#include extern uint8_t channelList[6]; @@ -10,4 +11,11 @@ uint8_t Zigbee_tx_buffer(uint8_t *tx_buffer, int len); void radioInit(); void radioSetChannel(uint8_t channel); void radioRxEnable(uint8_t channel); -void radioRxFlush(); \ No newline at end of file +void radioRxFlush(); + +struct zigbeeCalibDataStruct { + uint16_t len; + bool isValid; + uint32_t data[30]; +}; +extern __attribute__((section(".aon"))) volatile struct zigbeeCalibDataStruct zigbeeCalibData;