diff --git a/Marlin/AO_FT810_Constants.h b/Marlin/AO_FT810_Constants.h new file mode 100644 index 000000000..545f5beb9 --- /dev/null +++ b/Marlin/AO_FT810_Constants.h @@ -0,0 +1,645 @@ +/*********** + * FT810.h * + ***********/ + + +/**************************************************************************** + * Written By Mark Pelletier 2017 - Aleph Objects, Inc. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * To view a copy of the GNU General Public License, go to the following * + * location: . * + ****************************************************************************/ + +/**************************************************************************** + * This header defines registers and commands for the FTDI FT810 LCD Driver * + * chip. * + ****************************************************************************/ + + +/************************************************************************************************************ + * FT810 * + * * + * START ADDRESS END ADDRESS SIZE NAME DESCRIPTION * + * * + * 0x000000 0x0FFFFF 1024 kB RAM_G Main Graphics RAM 0 to 1048572 * + * * + * 0x0C0000 0x0C0003 4 B ROM_CHIPID [0:1] 0x800 [1:2] 0x0100 Chip Id, Version ID * + * * + * 0x1E0000 0x2FFFFB 1152 kB ROM_FONT Font table and bitmap * + * * + * 0x2FFFFC 0x2FFFFF 4 B ROM_FONT_ADDR Font table pointer address * + * * + * 0x300000 0x301FFF 8 kB RAM_DL Display List RAM * + * * + * 0x302000 0x302FFF 4 kB REG_* Registers * + * * + * 0x308000 0x308FFF 4 kB RAM_CMD Command Buffer * + * * + ************************************************************************************************************/ + +#ifndef _AO_FT810_H +#define _AO_FT810_H + +// Uncomment this line if using an Arduino board instead of a Printer Controller board. +// This allows the use of the Arduino SPI Library and SPI Peripheral instead of the bit-banged SPI +// of the Printer Controllers (RAMBo, Mini RAMBo, Einsy, Archim). +// This is used by the CLCD_spiTransfer(uint8_t) function and CLCD_spiInit() function. + +// #define IS_ARDUINO + +namespace FT800 { + // MEMORY LOCATIONS FT800 + const uint32_t RAM_G = 0x000000; // Main Graphics RAM + const uint32_t ROM_FONT = 0x0BB23C; // Font ROM + const uint32_t ROM_FONT_ADDR = 0x0FFFFC; // Font Table Pointer + const uint32_t RAM_DL = 0x100000; // Display List RAM + const uint32_t RAM_PAL = 0x102000; // Palette RAM + const uint32_t RAM_REG = 0x102400; // Registers + const uint32_t RAM_CMD = 0x108000; // Command Buffer +} + +namespace FT810 { + // MEMORY LOCATIONS FT810 + const uint32_t RAM_G = 0x000000; // Main Graphics RAM + const uint32_t ROM_CHIPID = 0x0C0000; // Chip ID ROM + const uint32_t ROM_FONT = 0x1E0000; // Font ROM + const uint32_t ROM_FONT_ADDR = 0x2FFFFC; // Font Table Pointer + const uint32_t RAM_DL = 0x300000; // Display List RAM + const uint32_t RAM_REG = 0x302000; // Registers + const uint32_t RAM_CMD = 0x308000; // Command Buffer +} + +namespace FT800 { + // REGISTERS AND ADDRESSES FT800 + + // REGISTER ADDRESS SIZE RESET VALUE TYPE DESCRIPTION + + const uint32_t REG_ID = 0x102400; // 8 0x7C r Identification Register, Always 0x7C + const uint32_t REG_FRAMES = 0x102404; // 32 0x00000000 r Frame Counter, Since Reset + const uint32_t REG_CLOCK = 0x102408; // 32 0x00000000 r Clock cycles, Since Reset + const uint32_t REG_FREQUENCY = 0x10240C; // 28 0x03938700 r/w Main Clock Frequency + const uint32_t REG_RENDERMODE = 0x102410; // 1 0x00 r/w Rendering Mode: 0 = normal, 1 = single-line + const uint32_t REG_SNAPY = 0x102414; // 11 0x0000 r/w Scan Line Select for RENDERMODE 1 + const uint32_t REG_SNAPSHOT = 0x102418; // 1 - r Trigger for RENDERMODE 1 + const uint32_t REG_CPURESET = 0x10241C; // 3 0x02 r/w RESET Bit2 Audio - Bit1 Touch - Bit0 Graphics + const uint32_t REG_TAP_CRC = 0x102420; // 32 - r Live Video Tap + const uint32_t REG_TAP_MASK = 0x102424; // 32 0xFFFFFFFF r/w Live Video Tap Mask + const uint32_t REG_HCYCLE = 0x102428; // 12 0x224 r/w Horizontal Total Cycle Count + const uint32_t REG_HOFFSET = 0x10242C; // 12 0x02B r/w Horizontal Display Start Offset + const uint32_t REG_HSIZE = 0x102430; // 12 0x1E0 r/w Horizontal Display Pixel Count + const uint32_t REG_HSYNC0 = 0x102434; // 12 0x000 r/w Horizontal Sync Fall Offset + const uint32_t REG_HSYNC1 = 0x102438; // 12 0x029 r/w Horizontal Sync Rise Offset + const uint32_t REG_VCYCLE = 0x10243C; // 12 0x124 r/w Vertical Total Cycle Count + const uint32_t REG_VOFFSET = 0x102440; // 12 0x00C r/w Vertical Display Start Offset + const uint32_t REG_VSIZE = 0x102444; // 12 0x110 r/w Vertical Display Line Count + const uint32_t REG_VSYNC0 = 0x102448; // 10 0x000 r/w Vertical Sync Fall Offset + const uint32_t REG_VSYNC1 = 0x10244C; // 10 0x00A r/w Vertical Sync Rise Offset + const uint32_t REG_DLSWAP = 0x102450; // 2 0x00 r/w Display List Swap Control + const uint32_t REG_ROTATE = 0x102454; // 3 0x00 r/w Screen 90,180, 270 degree rotate + const uint32_t REG_OUTBITS = 0x102458; // 9 0x1B6 r/w Output Resolution, 3x3x3 Bits + const uint32_t REG_DITHER = 0x10245C; // 1 0x01 r/w Output Dither Enable + const uint32_t REG_SWIZZLE = 0x102460; // 4 0x00 r/w Output RGB Swizzle, Pin Change for PCB Routing + const uint32_t REG_CSPREAD = 0x102464; // 1 0x01 r/w Output Clock Spreading Enable + const uint32_t REG_PCLK_POL = 0x102468; // 1 0x00 r/w PCLK Polarity: 0 = Rising Edge, 1 = Falling Edge + const uint32_t REG_PCLK = 0x10246C; // 8 0x00 r/w PCLK Frequency Divider, 0 = Disable Clock + const uint32_t REG_TAG_X = 0x102470; // 11 0x000 r/w Tag Query X Coordinate + const uint32_t REG_TAG_Y = 0x102474; // 11 0x000 r/w Tag Query Y Coordinate + const uint32_t REG_TAG = 0x102478; // 8 0x00 r Tag Query Result + const uint32_t REG_VOL_PB = 0x10247C; // 8 0xFF r/w Audio Playback Volume + const uint32_t REG_VOL_SOUND = 0x102480; // 8 0xFF r/w Audio Synthesizer Volume + const uint32_t REG_SOUND = 0x102484; // 16 0x0000 r/w Audio Sound Effect Select + const uint32_t REG_PLAY = 0x102488; // 1 0x00 r/w Audio Start Effect Playback + const uint32_t REG_GPIO_DIR = 0x10248C; // 8 0x80 r/w GPIO Pin Direction: 0 = Input , 1 = Output + const uint32_t REG_GPIO = 0x102490; // 8 0x00 r/w GPIO Pin Values for 0, 1, 7 Drive Strength 2, 3, 4, 5, 6 + const uint32_t REG_INT_FLAGS = 0x102498; // 8 0x00 r Interrupt Flags, Clear by Reading + const uint32_t REG_INT_EN = 0x10249C; // 1 0x00 r/w Global Interrupt Enable + const uint32_t REG_INT_MASK = 0x1024A0; // 8 0xFF r/w Interrupt Enable Mask + const uint32_t REG_PLAYBACK_START = 0x1024A4; // 20 0x00000 r/w Audio Playback RAM Start Address + const uint32_t REG_PLAYBACK_LENGTH = 0x1024A8; // 20 0x00000 r/w Audio Playback Sample Length (Bytes) + const uint32_t REG_PLAYBACK_READPTR = 0x1024AC; // 20 - r Audio Playback Read Pointer + const uint32_t REG_PLAYBACK_FREQ = 0x1024B0; // 16 0x1F40 r/w Audio Playback Frequency (Hz) + const uint32_t REG_PLAYBACK_FORMAT = 0x1024B4; // 2 0x00 r/w Audio Playback Format + const uint32_t REG_PLAYBACK_LOOP = 0x1024B8; // 1 0x00 r/w Audio Playback Loop Enable + const uint32_t REG_PLAYBACK_PLAY = 0x1024BC; // 1 0x00 r Audio Start Playback + const uint32_t REG_PWM_HZ = 0x1024C0; // 14 0x00FA r/w Backlight PWM Frequency (Hz) + const uint32_t REG_PWM_DUTY = 0x1024C4; // 8 0x80 r/w Backlight PWM Duty Cycle: 0 = 0%, 128 = 100% + const uint32_t REG_MACRO_0 = 0x1024C8; // 32 0x00000000 r/w Display List Macro Command 0 + const uint32_t REG_MACRO_1 = 0x1024CC; // 32 0x00000000 r/w Display List Macro Command 1 + const uint32_t REG_CMD_READ = 0x1024E4; // 12 0x000 r/w Command Buffer Read Pointer + const uint32_t REG_CMD_WRITE = 0x1024E8; // 12 0x000 r/w Command Buffer Write Pointer + const uint32_t REG_CMD_DL = 0x1024EC; // 13 0x0000 r/w Command Display List Offset + const uint32_t REG_TOUCH_MODE = 0x1024F0; // 2 0x03 r/w Touch-Screen Sampling Mode + const uint32_t REG_TOUCH_ADC_MODE = 0x1024F4; // 1 0x01 r/w Select Single Ended or Differential Sampling + const uint32_t REG_TOUCH_CHARGE = 0x1024F8; // 16 0x1770 r/w Touch Screen Charge Time, n x 6 Clocks + const uint32_t REG_TOUCH_SETTLE = 0x1024FC; // 4 0x03 r/w Touch-Screen Settle Time, n x 6 Clocks + const uint32_t REG_TOUCH_OVERSAMPLE = 0x102500; // 4 0x07 r/w Touch-Screen Oversample Factor + const uint32_t REG_TOUCH_RZTHRESH = 0x102504; // 16 0xFFFF r/w Touch-Screen Resistance Threshold + const uint32_t REG_TOUCH_RAW_XY = 0x102508; // 32 - r Touch-Screen Raw (x-MSB16; y-LSB16) + const uint32_t REG_TOUCH_RZ = 0x10250C; // 16 - r Touch-Screen Resistance + const uint32_t REG_TOUCH_SCREEN_XY = 0x102510; // 32 - r Touch-Screen Screen (x-MSB16; y-LSB16) + const uint32_t REG_TOUCH_TAG_XY = 0x102514; // 32 - r Touch-Screen Tag 0 Lookup (x-MSB16; y-LSB16) + const uint32_t REG_TOUCH_TAG = 0x102518; // 8 - r Touch-Screen Tag 0 Result + const uint32_t REG_TOUCH_TRANSFORM_A = 0x10251C; // 32 0x00010000 r/w Touch-Screen Transform Coefficient A (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_B = 0x102520; // 32 0x00000000 r/w Touch-Screen Transform Coefficient B (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_C = 0x102524; // 32 0x00000000 r/w Touch-Screen Transform Coefficient C (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_D = 0x102528; // 32 0x00000000 r/w Touch-Screen Transform Coefficient D (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_E = 0x10252C; // 32 0x00010000 r/w Touch-Screen Transform Coefficient E (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_F = 0x102530; // 32 0x00000000 r/w Touch-Screen Transform Coefficient F (s15.16) +// Reserved Addresses 0x102434 - 0x102470 + const uint32_t REG_TOUCH_DIRECT_XY = 0x102574; // 32 - r Touch-Screen Direct Conversions XY (x-MSB16; y-LSB16) + const uint32_t REG_TOUCH_DIRECT_Z1Z2 = 0x102578; // 32 - r Touch-Screen Direct Conversions Z (z1-MSB16; z2-LSB16) + const uint32_t REG_TRACKER = 0x109000; // 32 0x00000000 r/w Track Register (Track Value – MSB16; Tag Value - LSB8) +}; + +namespace FT810 { + // REGISTERS AND ADDRESSES FT810 + + // REGISTER ADDRESS SIZE RESET VALUE TYPE DESCRIPTION + + const uint32_t REG_ID = 0x302000; // 8 0x7C r Identification Register, Always 0x7C + const uint32_t REG_FRAMES = 0x302004; // 32 0x00000000 r Frame Counter, Since Reset + const uint32_t REG_CLOCK = 0x302008; // 32 0x00000000 r Clock cycles, Since Reset + const uint32_t REG_FREQUENCY = 0x30200C; // 28 0x03938700 r/w Main Clock Frequency + const uint32_t REG_RENDERMODE = 0x302010; // 1 0x00 r/w Rendering Mode: 0 = normal, 1 = single-line + const uint32_t REG_SNAPY = 0x302014; // 11 0x0000 r/w Scan Line Select for RENDERMODE 1 + const uint32_t REG_SNAPSHOT = 0x302018; // 1 - r Trigger for RENDERMODE 1 + const uint32_t REG_SNAPFORMAT = 0x30201C; // 6 0x20 r/w Pixel Format for Scanline Readout + const uint32_t REG_CPURESET = 0x302020; // 3 0x02 r/w RESET Bit2 Audio - Bit1 Touch - Bit0 Graphics + const uint32_t REG_TAP_CRC = 0x302024; // 32 - r Live Video Tap + const uint32_t REG_TAP_MASK = 0x302028; // 32 0xFFFFFFFF r/w Live Video Tap Mask + const uint32_t REG_HCYCLE = 0x30202C; // 12 0x224 r/w Horizontal Total Cycle Count + const uint32_t REG_HOFFSET = 0x302030; // 12 0x02B r/w Horizontal Display Start Offset + const uint32_t REG_HSIZE = 0x302034; // 12 0x1E0 r/w Horizontal Display Pixel Count + const uint32_t REG_HSYNC0 = 0x302038; // 12 0x000 r/w Horizontal Sync Fall Offset + const uint32_t REG_HSYNC1 = 0x30203C; // 12 0x029 r/w Horizontal Sync Rise Offset + const uint32_t REG_VCYCLE = 0x302040; // 12 0x124 r/w Vertical Total Cycle Count + const uint32_t REG_VOFFSET = 0x302044; // 12 0x00C r/w Vertical Display Start Offset + const uint32_t REG_VSIZE = 0x302048; // 12 0x110 r/w Vertical Display Line Count + const uint32_t REG_VSYNC0 = 0x30204C; // 10 0x000 r/w Vertical Sync Fall Offset + const uint32_t REG_VSYNC1 = 0x302050; // 10 0x00A r/w Vertical Sync Rise Offset + const uint32_t REG_DLSWAP = 0x302054; // 2 0x00 r/w Display List Swap Control + const uint32_t REG_ROTATE = 0x302058; // 3 0x00 r/w Screen 90,180, 270 degree rotate + const uint32_t REG_OUTBITS = 0x30205C; // 9 0x1B6 r/w Output Resolution, 3x3x3 Bits + const uint32_t REG_DITHER = 0x302060; // 1 0x01 r/w Output Dither Enable + const uint32_t REG_SWIZZLE = 0x302064; // 4 0x00 r/w Output RGB Swizzle, Pin Change for PCB Routing + const uint32_t REG_CSPREAD = 0x302068; // 1 0x01 r/w Output Clock Spreading Enable + const uint32_t REG_PCLK_POL = 0x30206C; // 1 0x00 r/w PCLK Polarity: 0 = Rising Edge, 1 = Falling Edge + const uint32_t REG_PCLK = 0x302070; // 8 0x00 r/w PCLK Frequency Divider, 0 = Disable Clock + const uint32_t REG_TAG_X = 0x302074; // 11 0x000 r/w Tag Query X Coordinate + const uint32_t REG_TAG_Y = 0x302078; // 11 0x000 r/w Tag Query Y Coordinate + const uint32_t REG_TAG = 0x30207C; // 8 0x00 r Tag Query Result + const uint32_t REG_VOL_PB = 0x302080; // 8 0xFF r/w Audio Playback Volume + const uint32_t REG_VOL_SOUND = 0x302084; // 8 0xFF r/w Audio Synthesizer Volume + const uint32_t REG_SOUND = 0x302088; // 16 0x0000 r/w Audio Sound Effect Select + const uint32_t REG_PLAY = 0x30208C; // 1 0x00 r/w Audio Start Effect Playback + const uint32_t REG_GPIO_DIR = 0x302090; // 8 0x80 r/w GPIO Pin Direction: 0 = Input , 1 = Output + const uint32_t REG_GPIO = 0x302094; // 8 0x00 r/w GPIO Pin Values for 0, 1, 7 Drive Strength 2, 3, 4, 5, 6 + const uint32_t REG_GPIOX_DIR = 0x302098; // 16 0x8000 r/w Extended GPIO Pin Direction + const uint32_t REG_GPIOX = 0x30209C; // 16 0x0080 r/w Extended GPIO Pin Values + // Reserved Addr 0x3020A0 + // Reserved Addr 0x3020A4 + const uint32_t REG_INT_FLAGS = 0x3020A8; // 8 0x00 r Interrupt Flags, Clear by Reading + const uint32_t REG_INT_EN = 0x3020AC; // 1 0x00 r/w Global Interrupt Enable + const uint32_t REG_INT_MASK = 0x3020B0; // 8 0xFF r/w Interrupt Enable Mask + const uint32_t REG_PLAYBACK_START = 0x3020B4; // 20 0x00000 r/w Audio Playback RAM Start Address + const uint32_t REG_PLAYBACK_LENGTH = 0x3020B8; // 20 0x00000 r/w Audio Playback Sample Length (Bytes) + const uint32_t REG_PLAYBACK_READPTR = 0x3020BC; // 20 - r Audio Playback Read Pointer + const uint32_t REG_PLAYBACK_FREQ = 0x3020C0; // 16 0x1F40 r/w Audio Playback Frequency (Hz) + const uint32_t REG_PLAYBACK_FORMAT = 0x3020C4; // 2 0x00 r/w Audio Playback Format + const uint32_t REG_PLAYBACK_LOOP = 0x3020C8; // 1 0x00 r/w Audio Playback Loop Enable + const uint32_t REG_PLAYBACK_PLAY = 0x3020CC; // 1 0x00 r Audio Start Playback + const uint32_t REG_PWM_HZ = 0x3020D0; // 14 0x00FA r/w Backlight PWM Frequency (Hz) + const uint32_t REG_PWM_DUTY = 0x3020D4; // 8 0x80 r/w Backlight PWM Duty Cycle: 0 = 0%, 128 = 100% + const uint32_t REG_MACRO_0 = 0x3020D8; // 32 0x00000000 r/w Display List Macro Command 0 + const uint32_t REG_MACRO_1 = 0x3020DC; // 32 0x00000000 r/w Display List Macro Command 1 + // Reserved Addr 0x3020E0 + // Reserved Addr 0x3020E4 + // Reserved Addr 0x3020E8 + // Reserved Addr 0x3020EC + // Reserved Addr 0x3020F0 + // Reserved Addr 0x3020F4 + const uint32_t REG_CMD_READ = 0x3020F8; // 12 0x000 r/w Command Buffer Read Pointer + const uint32_t REG_CMD_WRITE = 0x3020FC; // 12 0x000 r/w Command Buffer Write Pointer + const uint32_t REG_CMD_DL = 0x302100; // 13 0x0000 r/w Command Display List Offset + const uint32_t REG_TOUCH_MODE = 0x302104; // 2 0x03 r/w Touch-Screen Sampling Mode + const uint32_t REG_TOUCH_ADC_MODE = 0x302108; // 1 0x01 r/w Select Single Ended or Differential Sampling + const uint32_t REG_TOUCH_CHARGE = 0x30210C; // 16 0x1770 r/w Touch Screen Charge Time, n x 6 Clocks + const uint32_t REG_TOUCH_SETTLE = 0x302110; // 4 0x03 r/w Touch-Screen Settle Time, n x 6 Clocks + const uint32_t REG_TOUCH_OVERSAMPLE = 0x302114; // 4 0x07 r/w Touch-Screen Oversample Factor + const uint32_t REG_TOUCH_RZTHRESH = 0x302118; // 16 0xFFFF r/w Touch-Screen Resistance Threshold + const uint32_t REG_TOUCH_RAW_XY = 0x30211C; // 32 - r Touch-Screen Raw (x-MSB16; y-LSB16) + const uint32_t REG_TOUCH_RZ = 0x302120; // 16 - r Touch-Screen Resistance + const uint32_t REG_TOUCH_SCREEN_XY = 0x302124; // 32 - r Touch-Screen Screen (x-MSB16; y-LSB16) + const uint32_t REG_TOUCH_TAG_XY = 0x302128; // 32 - r Touch-Screen Tag 0 Lookup (x-MSB16; y-LSB16) + const uint32_t REG_TOUCH_TAG = 0x30212C; // 8 - r Touch-Screen Tag 0 Result + const uint32_t REG_TOUCH_TAG1_XY = 0x302130; // 32 - r Touch-Screen Tag 1 Lookup + const uint32_t REG_TOUCH_TAG1 = 0x302134; // 8 - r Touch-Screen Tag 1 Result + const uint32_t REG_TOUCH_TAG2_XY = 0x302138; // 32 - r Touch-Screen Tag 2 Lookup + const uint32_t REG_TOUCH_TAG2 = 0x30213C; // 8 - r Touch-Screen Tag 2 Result + const uint32_t REG_TOUCH_TAG3_XY = 0x302140; // 32 - r Touch-Screen Tag 3 Lookup + const uint32_t REG_TOUCH_TAG3 = 0x302144; // 8 - r Touch-Screen Tag 3 Result + const uint32_t REG_TOUCH_TAG4_XY = 0x302148; // 32 - r Touch-Screen Tag 4 Lookup + const uint32_t REG_TOUCH_TAG4 = 0x30214C; // 8 - r Touch-Screen Tag 4 Result + const uint32_t REG_TOUCH_TRANSFORM_A = 0x302150; // 32 0x00010000 r/w Touch-Screen Transform Coefficient A (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_B = 0x302154; // 32 0x00000000 r/w Touch-Screen Transform Coefficient B (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_C = 0x302158; // 32 0x00000000 r/w Touch-Screen Transform Coefficient C (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_D = 0x30215C; // 32 0x00000000 r/w Touch-Screen Transform Coefficient D (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_E = 0x302160; // 32 0x00010000 r/w Touch-Screen Transform Coefficient E (s15.16) + const uint32_t REG_TOUCH_TRANSFORM_F = 0x302164; // 32 0x00000000 r/w Touch-Screen Transform Coefficient F (s15.16) + const uint32_t REG_TOUCH_CONFIG = 0x302168; // 16 0x8381 r/w Touch Configuration + const uint32_t REG_CTOUCH_TOUCH4_X = 0x30216C; // 16 - r Extended Mode Touch Screen + // Reserved Addresses 0x302170 + const uint32_t REG_BIST_EN = 0x302174; // 1 0 r/w BIST Memory Mapping Enable + // Reserved Addr 0x302178 + // Reserved Addr 0x30217C + const uint32_t REG_TRIM = 0x302180; // 8 0 r/w Internal Clock Trimming + const uint32_t REG_ANA_COMP = 0x302184; // 8 0 r/w Analog Control Register + const uint32_t REG_SPI_WIDTH = 0x302188; // 3 0 r/w QSPI Bus Width Setting + const uint32_t REG_TOUCH_DIRECT_XY = 0x30218C; // 32 - r Touch-Screen Direct Conversions XY (x-MSB16; y-LSB16) + const uint32_t REG_TOUCH_DIRECT_Z1Z2 = 0x302190; // 32 - r Touch-Screen Direct Conversions Z (z1-MSB16; z2-LSB16) + // Reserved Addresses 0x302194 - 0x302560 + const uint32_t REG_DATESTAMP = 0x320564; // 128 - r Stamp Date Code + const uint32_t REG_CMDB_SPACE = 0x302574; // 12 0xFFC r/w Command DL Space Available + const uint32_t REG_CMDB_WRITE = 0x302578; // 32 0 w Command DL Write +} + +// OPTIONS + +namespace FTDI { + const uint16_t OPT_3D = 0; + const uint16_t OPT_RGB565 = 0; + const uint16_t OPT_MONO = 1; + const uint16_t OPT_NODL = 2; + const uint16_t OPT_FLAT = 256; + const uint16_t OPT_SIGNED = 256; + const uint16_t OPT_CENTERX = 512; + const uint16_t OPT_CENTERY = 1024; + const uint16_t OPT_CENTER = 1536; + const uint16_t OPT_RIGHTX = 2048; + const uint16_t OPT_NOBACK = 4096; + const uint16_t OPT_NOTICKS = 8192; + const uint16_t OPT_NOHM = 16384; + const uint16_t OPT_NOPOINTER = 16384; + const uint16_t OPT_NOSECS = 32768; + const uint16_t OPT_NOHANDS = 49152; +} + +// GLOBAL LCD REGISTER SET VALUES FOR WQVGA 480x272 DISPLAY + +/* + * Settings for the Aleph Objects Color LCD User Interface 4.3" (Prototype) 480x272, SPI, FT810 (HDA430T-6S-WV) + * Haoyu Electronics, 4.3" Graphical LCD Touchscreen, 480x272, SPI, FT800 (FT800CB-HY43B) + * Haoyu Electronics, 5" Graphical LCD Touchscreen, 480x272, SPI, FT800 (FT800CB-HY50B) + * 4D Systems, 4.3" Embedded SPI Display 480x272, SPI, FT800 (4DLCD-FT843) + * + * http://www.hotmcu.com/43-graphical-lcd-touchscreen-480x272-spi-ft800-p-111.html?cPath=6_16 + * http://www.hotmcu.com/5-graphical-lcd-touchscreen-480x272-spi-ft800-p-124.html?cPath=6_16 + * http://www.4dsystems.com.au/product/4DLCD_FT843/ + * + * Datasheet: + * + * http://www.hantronix.com/files/data/1278363262430-3.pdf + * http://www.haoyuelectronics.com/Attachment/HY43-LCD/LCD%20DataSheet.pdf + * http://www.haoyuelectronics.com/Attachment/HY5-LCD-HD/KD50G21-40NT-A1.pdf + * http://www.4dsystems.com.au/productpages/4DLCD-FT843/downloads/FT843-4.3-Display_datasheet_R_1_2.pdf + * + */ +namespace FTDI_LCD_480x272 { + const int Vsync0 = 0; + const int Vsync1 = 10; + const int Voffset = 12; + const int Vcycle = 292; + const int Hsync0 = 0; + const int Hsync1 = 41; + const int Hoffset = 43; + const int Hcycle = 548; + const int Hsize = 480; + const int Vsize = 272; + const int Pclkpol = 1; + const int Swizzle = 0; + const int Pclk = 5; + const int Clksel = 0x44; + + const uint32_t default_transform_a = 0x00008100; + const uint32_t default_transform_b = 0x00000000; + const uint32_t default_transform_c = 0xFFF18000; + const uint32_t default_transform_d = 0x00000000; + const uint32_t default_transform_e = 0xFFFFB100; + const uint32_t default_transform_f = 0x0120D000; +} + +// GLOBAL LCD REGISTER SET VALUES FOR 800x480 DISPLAY + +/* + * Settings for the Haoyu Electronics, 5" Graphical LCD Touchscreen, 800x480, SPI, FT810 + * + * http://www.hotmcu.com/5-graphical-lcd-touchscreen-800x480-spi-ft810-p-286.html + * + * Datasheet: + * + * http://www.haoyuelectronics.com/Attachment/HY5-LCD-HD/KD50G21-40NT-A1.pdf + * + */ +namespace FTDI_LCD_800x480 { + const int Vsync0 = 0; + const int Vsync1 = 13; + const int Voffset = 16; + const int Vcycle = 525; + const int Hsync0 = 0; + const int Hsync1 = 40; + const int Hoffset = 88; + const int Hcycle = 928; + const int Hsize = 800; + const int Vsize = 480; + const int Pclkpol = 1; + const int Swizzle = 0; + const int Pclk = 2; + const int Clksel = 0x45; + + const uint32_t default_transform_a = 0x0000012B; + const uint32_t default_transform_b = 0xFFFF7BFC; + const uint32_t default_transform_c = 0x01F2443A; + const uint32_t default_transform_d = 0xFFFF25ED; + const uint32_t default_transform_e = 0x000000F9; + const uint32_t default_transform_f = 0x033F61DA; +} + +// HOST COMMANDS + +namespace FTDI { + const uint8_t ACTIVE = 0x00; + const uint8_t STANDBY = 0x41; + const uint8_t SLEEP = 0x42; + const uint8_t PWRDOWN = 0x50; + const uint8_t CLKEXT = 0x44; + const uint8_t CLKINT = 0x48; + const uint8_t CORESET = 0x68; +} +namespace FT800 { + const uint8_t CLK48M = 0x62; + const uint8_t CLK36M = 0x61; +} +namespace FT810 { + const uint8_t CLKSEL = 0x61; +} + +// DISPLAY LIST COMMANDS + +namespace FTDI { + const uint32_t ALPHA_FUNC = 0x09000000; + + const uint32_t ALPHA_FUNC_NEVER = 0x00000000; + const uint32_t ALPHA_FUNC_LESS = 0x00010000; + const uint32_t ALPHA_FUNC_LEQUAL = 0x00020000; + const uint32_t ALPHA_FUNC_GREATER = 0x00030000; + const uint32_t ALPHA_FUNC_GEQUAL = 0x00040000; + const uint32_t ALPHA_FUNC_EQUAL = 0x00050000; + const uint32_t ALPHA_FUNC_NOTEQUAL = 0x00060000; + const uint32_t ALPHA_FUNC_ALWAYS = 0x00070000; + + const uint32_t BEGIN = 0x1F000000; + + const uint32_t BEGIN_BITMAPS = 0x00000001; + const uint32_t BEGIN_POINTS = 0x00000002; + const uint32_t BEGIN_LINES = 0x00000003; + const uint32_t BEGIN_LINE_STRIP = 0x00000004; + const uint32_t BEGIN_STRIP_R = 0x00000005; + const uint32_t BEGIN_STRIP_L = 0x00000006; + const uint32_t BEGIN_STRIP_A = 0x00000007; + const uint32_t BEGIN_STRIP_B = 0x00000008; + const uint32_t BEGIN_STRIP_RECTS = 0x00000009; + + const uint32_t BITMAP_HANDLE = 0x05000000; + + const uint32_t BITMAP_LAYOUT = 0x07000000; + + const uint32_t BITMAP_LAYOUT_ARGB1555 = 0x00000000; + const uint32_t BITMAP_LAYOUT_L1 = 0x00080000; + const uint32_t BITMAP_LAYOUT_L4 = 0x00100000; + const uint32_t BITMAP_LAYOUT_L8 = 0x00180000; + const uint32_t BITMAP_LAYOUT_RGB332 = 0x00200000; + const uint32_t BITMAP_LAYOUT_ARGB2 = 0x00280000; + const uint32_t BITMAP_LAYOUT_ARGB4 = 0x00300000; + const uint32_t BITMAP_LAYOUT_RGB565 = 0x00380000; + const uint32_t BITMAP_LAYOUT_PALETTED = 0x00400000; + const uint32_t BITMAP_LAYOUT_TEXT8X8 = 0x00480000; + const uint32_t BITMAP_LAYOUT_TEXTVGA = 0x00500000; + const uint32_t BITMAP_LAYOUT_BARGRAPH = 0x00580000; + + const uint8_t ARGB1555 = 0x00; + const uint8_t L1 = 0x01; + const uint8_t L4 = 0x02; + const uint8_t L8 = 0x03; + const uint8_t RGB332 = 0x04; + const uint8_t ARGB2 = 0x05; + const uint8_t ARGB4 = 0x06; + const uint8_t RGB565 = 0x07; + const uint8_t PALETTED = 0x08; + const uint8_t TEXT8X8 = 0x09; + const uint8_t TEXTVGA = 0x0A; + const uint8_t BARGRAPH = 0x0B; + + const uint32_t BITMAP_SIZE = 0x08000000; + + const uint8_t NEAREST = 0x00; + const uint8_t BILINEAR = 0x01; + const uint8_t BORDER = 0x00; + const uint8_t REPEAT = 0x01; + + const uint32_t BITMAP_SOURCE = 0x01000000; + + const uint32_t BITMAP_TRANSFORM_A = 0x15000000; + + const uint32_t BITMAP_TRANSFORM_B = 0x16000000; + + const uint32_t BITMAP_TRANSFORM_C = 0x17000000; + + const uint32_t BITMAP_TRANSFORM_D = 0x18000000; + + const uint32_t BITMAP_TRANSFORM_E = 0x19000000; + + const uint32_t BITMAP_TRANSFORM_F = 0x1A000000; + + const uint32_t BLEND_FUNC = 0x0B000000; + + const uint32_t BLEND_FUNC_SRC_ZERO = 0x00000000; + const uint32_t BLEND_FUNC_SRC_ONE = 0x00000008; + const uint32_t BLEND_FUNC_SRC_SRC_ALPHA = 0x00000010; + const uint32_t BLEND_FUNC_SRC_DST_ALPHA = 0x00000018; + const uint32_t BLEND_FUNC_SRC_ONE_MINUS_SRC_ALPHA = 0x00000020; + const uint32_t BLEND_FUNC_SRC_ONE_MINUS_DST_ALPHA = 0x00000028; + + const uint32_t BLEND_FUNC_DST_ZERO = 0x00000000; + const uint32_t BLEND_FUNC_DST_ONE = 0x00000001; + const uint32_t BLEND_FUNC_DST_SRC_ALPHA = 0x00000002; + const uint32_t BLEND_FUNC_DST_DST_ALPHA = 0x00000003; + const uint32_t BLEND_FUNC_DST_ONE_MINUS_SRC_ALPHA = 0x00000004; + const uint32_t BLEND_FUNC_DST_ONE_MINUS_DST_ALPHA = 0x00000005; + + const uint32_t CALL = 0x1D000000; + + const uint32_t CELL = 0x06000000; + + const uint32_t CLEAR = 0x26000000; + + const uint32_t CLEAR_COLOR_BUFFER = 0x00000004; + const uint32_t CLEAR_STENCIL_BUFFER = 0x00000002; + const uint32_t CLEAR_TAG_BUFFER = 0x00000001; + + const uint32_t CLEAR_COLOR_A = 0x0F000000; + + const uint32_t CLEAR_COLOR_RGB = 0x02000000; + + const uint32_t CLEAR_STENCIL = 0x11000000; + + const uint32_t CLEAR_TAG = 0x12000000; + + const uint32_t COLOR_A = 0x10000000; + + const uint32_t COLOR_MASK = 0x20000000; + + const uint32_t COLOR_MASK_RED = 0x00000008; + const uint32_t COLOR_MASK_GRN = 0x00000004; + const uint32_t COLOR_MASK_BLU = 0x00000002; + const uint32_t COLOR_MASK_ALPHA = 0x00000001; + + const uint32_t COLOR_RGB = 0x04000000; + + const uint32_t DL_DISPLAY = 0x00000000; + + const uint32_t END = 0x21000000; + + const uint32_t JUMP = 0x1E000000; + + const uint32_t LINE_WIDTH = 0x0E000000; + + const uint32_t MACRO = 0x25000000; + + const uint32_t POINT_SIZE = 0x0D000000; + + const uint32_t RESTORE_CONTEXT = 0x23000000; + + const uint32_t RETURN = 0x24000000; + + const uint32_t SAVE_CONTEXT = 0x22000000; + + const uint32_t SCISSOR_SIZE = 0x1C000000; + + const uint32_t SCISSOR_XY = 0x1B000000; + + const uint32_t STENCIL_FUNC = 0x0A000000; + + const uint32_t STENCIL_FUNC_NEVER = 0x00000000; + const uint32_t STENCIL_FUNC_LESS = 0x00010000; + const uint32_t STENCIL_FUNC_LEQUAL = 0x00020000; + const uint32_t STENCIL_FUNC_GREATER = 0x00030000; + const uint32_t STENCIL_FUNC_GEQUAL = 0x00040000; + const uint32_t STENCIL_FUNC_EQUAL = 0x00050000; + const uint32_t STENCIL_FUNC_NOTEQUAL = 0x00060000; + const uint32_t STENCIL_FUNC_ALWAYS = 0x00070000; + + const uint32_t STENCIL_MASK = 0x13000000; + + const uint32_t STENCIL_OP = 0x0C000000; + + const uint32_t STENCIL_OP_PASS_ZERO = 0x00000000; + const uint32_t STENCIL_OP_PASS_KEEP = 0x00000001; + const uint32_t STENCIL_OP_PASS_REPLACE = 0x00000002; + const uint32_t STENCIL_OP_PASS_INCR = 0x00000003; + const uint32_t STENCIL_OP_PASS_DECR = 0x00000004; + const uint32_t STENCIL_OP_PASS_INVERT = 0x00000005; + + const uint32_t STENCIL_OP_FAIL_ZERO = 0x00000000; + const uint32_t STENCIL_OP_FAIL_KEEP = 0x00000008; + const uint32_t STENCIL_OP_FAIL_REPLACE = 0x00000010; + const uint32_t STENCIL_OP_FAIL_INCR = 0x00000018; + const uint32_t STENCIL_OP_FAIL_DECR = 0x00000020; + const uint32_t STENCIL_OP_FAIL_INVERT = 0x00000028; + + const uint32_t TAG = 0x03000000; + + const uint32_t TAG_MASK = 0x14000000; + + const uint32_t VERTEX2F = 0x40000000; + + const uint32_t VERTEX2II = 0x80000000; +} + +// CO-PROCESSOR ENGINE COMMANDS +namespace FTDI { + const uint32_t CMD_DLSTART = 0xFFFFFF00; + const uint32_t CMD_SWAP = 0xFFFFFF01; + const uint32_t CMD_COLDSTART = 0xFFFFFF32; + const uint32_t CMD_INTERRUPT = 0xFFFFFF02; + const uint32_t CMD_APPEND = 0xFFFFFF1E; + const uint32_t CMD_REGREAD = 0xFFFFFF19; + const uint32_t CMD_MEMWRITE = 0xFFFFFF1A; + const uint32_t CMD_INFLATE = 0xFFFFFF22; + const uint32_t CMD_LOADIMAGE = 0xFFFFFF24; + const uint32_t CMD_MEMCRC = 0xFFFFFF18; + const uint32_t CMD_MEMZERO = 0xFFFFFF1C; + const uint32_t CMD_MEMSET = 0xFFFFFF1B; + const uint32_t CMD_MEMCPY = 0xFFFFFF1D; + const uint32_t CMD_BUTTON = 0xFFFFFF0D; + const uint32_t CMD_CLOCK = 0xFFFFFF14; + const uint32_t CMD_FGCOLOR = 0xFFFFFF0A; + const uint32_t CMD_BGCOLOR = 0xFFFFFF09; + const uint32_t CMD_GRADCOLOR = 0xFFFFFF34; + const uint32_t CMD_GAUGE = 0xFFFFFF13; + const uint32_t CMD_GRADIENT = 0xFFFFFF0B; + const uint32_t CMD_KEYS = 0xFFFFFF0E; + const uint32_t CMD_PROGRESS = 0xFFFFFF0F; + const uint32_t CMD_SCROLLBAR = 0xFFFFFF11; + const uint32_t CMD_SLIDER = 0xFFFFFF10; + const uint32_t CMD_DIAL = 0xFFFFFF2D; + const uint32_t CMD_TOGGLE = 0xFFFFFF12; + const uint32_t CMD_TEXT = 0xFFFFFF0C; + const uint32_t CMD_NUMBER = 0xFFFFFF2E; + const uint32_t CMD_LOADIDENTITY = 0xFFFFFF26; + const uint32_t CMD_SETMATRIX = 0xFFFFFF2A; + const uint32_t CMD_GETMATRIX = 0xFFFFFF33; + const uint32_t CMD_GETPTR = 0xFFFFFF23; + const uint32_t CMD_GETPROPS = 0xFFFFFF25; + const uint32_t CMD_SCALE = 0xFFFFFF28; + const uint32_t CMD_ROTATE = 0xFFFFFF29; + const uint32_t CMD_TRANSLATE = 0xFFFFFF27; + const uint32_t CMD_CALIBRATE = 0xFFFFFF15; + const uint32_t CMD_SPINNER = 0xFFFFFF16; + const uint32_t CMD_SCREENSAVER = 0xFFFFFF2F; + const uint32_t CMD_SKETCH = 0xFFFFFF30; + const uint32_t CMD_STOP = 0xFFFFFF17; + const uint32_t CMD_SETFONT = 0xFFFFFF2B; + const uint32_t CMD_TRACK = 0xFFFFFF2C; + const uint32_t CMD_SNAPSHOT = 0xFFFFFF1F; + const uint32_t CMD_LOGO = 0xFFFFFF31; +} + +// If IS_FT800 is defined, then copy the FT800 namespace into the FTDI namespace +// If IS_FT810 is defined, then copy the FT810 namespace into the FTDI namespace + +#if defined(IS_FT800) +namespace FTDI { + using namespace FT800; +} +#elif defined(IS_FT810) +namespace FTDI { + using namespace FT810; +} +#endif + +#endif // _AO_FT810_H + + + + + diff --git a/Marlin/AO_FT810_Functions.h b/Marlin/AO_FT810_Functions.h new file mode 100644 index 000000000..afe2eb32d --- /dev/null +++ b/Marlin/AO_FT810_Functions.h @@ -0,0 +1,739 @@ +/********************* + * FT810_Functions.h * + *********************/ + + +/**************************************************************************** + * Written By Mark Pelletier 2017 - Aleph Objects, Inc. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * To view a copy of the GNU General Public License, go to the following * + * location: . * + ****************************************************************************/ + + /**************************************************************************** + * FUNCTION MAP * + * * + * SPI and FT800/810 Commands * + * * + * CLCD::spiSelect() Set CS line to 0 * + * CLCD::spiDeselect() Set CS Line to 1 * + * CLCD::Reset() Toggle FT800/810 Power Down Line 50 ms * + * CLCD::spiInit() Configure I/O Lines for SPI * + * CLCD::spiTransfer() Send/Receive 1 SPI Byte * + * CLCD::Init() Set FT800/810 Registers * + * CLCD::Enable() Turn On FT800/810 PCLK * + * CLCD::Disable() Turn Off FT8880/810 PCLK * + * CLCD::Set_Backlight() Set LCD Backlight Level * + * * + * MEMORY READ FUNCTIONS * + * * + * CLCD::Mem_ReadAddr() Send 32-Bit Address * + * CLCD::Mem_Read8() Read 1 Byte * + * CLCD::Mem_Read16() Read 2 Bytes * + * CLCD::Mem_Read32() Read 4 Bytes * + * * + * MEMORY WRITE FUNCTIONS * + * * + * CLCD::Mem_WriteAddr() Send 24-Bit Address * + * CLCD::Mem_Write8() Write 1 Byte * + * CLCD::Mem_Write16() Write 2 Bytes * + * CLCD::Mem_Write32() Write 4 Bytes * + * * + * HOST COMMAND FUNCTION * + * * + * CLCD::Host_Cmd() Send 24-Bit Host Command * + * * + * COMMAND BUFFER FUNCTIONS * + * * + * CLCD::Cmd() Send 32-Bit Value(4 Bytes)CMD Buffer * + * CLCD::Cmd() Send Data Structure with 32-Bit Cmd * + * CLCD::Cmd_Str() Send Text String in 32-Bit Multiples * + + * * + * FT800/810 GRAPHIC COMMANDS * + * * + * class CLCD:CommandFifo {} Class to control Cmd FIFO * + + * Fifo::Start() Wait for CP finish - Set FIFO Ptr * + * Fifo::Execute() Set REG_CMD_WRITE and start CP * + * Fifo::Reset() Set Cmd Buffer Pointers to 0 * + * + * Fifo::Cmd_Clear_Color() Set Clear Screen Color * + * Fifo::Cmd_Clear() Clear Color-Stencil-Tag Buffer(s) * + * Fifo::Cmd_Color() Set Current Color * + * Fifo::Cmd_Set_Foreground_Color Set Graphic Item Foreground Color * + * Fifo::Cmd_Set_Background_Color Set Graphic Item Background Color * + * Fifo::Cmd_Bitmap_Source() Set RAM Address of Bitmap Data * + * Fifo::Cmd_Bitmap_Layout() Configure Bitmap Format and Layout * + * Fifo::Cmd_Bitmap_Size() Set Bitmap Dimensions * + * Fifo::Cmd_Bitmap_Handle() Assign Handle ID to a Bitmap * + * Fifo::Cmd_Begin() Begin Drawing a Primative * + * Fifo::Cmd_Mem_Copy() Copy a Block of Memory * + * Fifo::Cmd_Append() Append Commands to Current DL * + * Fifo::Cmd_Gradient_Color() Set 3D Button Highlight Color * + * Fifo::Cmd_Vertex_2II() Set Coordinates of Graphics Primative * + * Fifo::Cmd_Draw_Button() Draw Button with Bulk Write * + * Fifo::Cmd_Draw_Text() Draw Text with Bulk Write * + * + * + */ + + + /************************************************** + * RAM_G Graphics RAM Allocation * + * * + * Address Use * + * * + * 8000 Extruder Bitmap * + * 8100 Bed Heat Bitmap * + * 8200 Fan Bitmap * + * 8300 Thumb Drive Symbol Bitmap * + * 3E000 Static DL Space (FT800) * + * FE000 Static DL Space (FT810) * + **************************************************/ + +#ifndef _AO_FT810_FUNC_H +#define _AO_FT810_FUNC_H + +#if defined(IS_FT800) + #define DL_CACHE_START 0x03E000 +#else + #define DL_CACHE_START 0x0FE000 +#endif + +#if defined(LCD_800x480) +using namespace FTDI_LCD_800x480; +#else +using namespace FTDI_LCD_480x272; +#endif + +using namespace FTDI; + +typedef const __FlashStringHelper *progmem_str; + +#define FORCEDINLINE __attribute__((always_inline)) + +class CLCD { + private: + static void spiInit (void); + static void spiSelect (void); + static void spiDeselect (void); + static uint8_t spiTransfer (uint8_t spiOutByte); + static void Mem_ReadAddr (uint32_t Reg_Address); + static void Mem_WriteAddr (uint32_t Reg_Address); + static void Mem_Read_Bulk (uint32_t Reg_Address, uint8_t *Data, uint16_t Len); + static void Mem_Write_Bulk (uint32_t Reg_Address, const void *Data, uint16_t Len, uint8_t Padding = 0); + static void Mem_Write_Bulk (uint32_t Reg_Address, progmem_str Str, uint16_t Len, uint8_t Padding = 0); + + public: + static uint8_t Mem_Read8 (uint32_t Reg_Address); + static uint16_t Mem_Read16 (uint32_t Reg_Address); + static uint32_t Mem_Read32 (uint32_t Reg_Address); + static void Mem_Write8 (uint32_t Reg_Address, uint8_t W_Data); + static void Mem_Write16 (uint32_t Reg_Address, uint16_t W_Data); + static void Mem_Write32 (uint32_t Reg_Address, uint32_t W_Data); + + static inline uint32_t pack_rgb(uint8_t r, uint8_t g, uint8_t b); + + public: + typedef struct { + const uint8_t format; + const uint16_t linestride; + const uint8_t filter; + const uint8_t wrapx; + const uint8_t wrapy; + const uint32_t RAMG_addr; + const uint16_t width; + const uint16_t height; + } bitmap_info_t; + + class CommandFifo { + protected: + static uint32_t getRegCmdWrite(); + static uint32_t getRegCmdRead(); + + #if defined(IS_FT800) + uint32_t command_write_ptr; + template void _write_unaligned(T data, uint16_t len); + #else + uint32_t getRegCmdBSpace(); + #endif + public: + + template void write(T data, uint16_t len); + + public: + static void Reset (void); + static bool Is_Idle(); + static void Wait_Until_Idle(); + + void Cmd_Start(void); + void Cmd_Execute(void); + + void Cmd (uint32_t cmd32); + void Cmd (void* data, uint16_t len); + void Cmd_Str (char* data); + void Cmd_Str (progmem_str data); + void Cmd_Clear_Color (uint32_t rgb); + void Cmd_Clear (bool Clr, bool Stl, bool Tag); + void Cmd_Color (uint32_t rgb); + void Cmd_Set_Foreground_Color (uint32_t rgb); + void Cmd_Set_Background_Color (uint32_t rgb); + void Cmd_Set_Tag (uint8_t Tag); + void Cmd_Bitmap_Source (uint32_t RAM_G_Addr); + + // The following functions *must* be inlined since we are relying on the compiler to do + // substitution of the constants from the data structure rather than actually storing + // it in PROGMEM (which would fail, since we are not using pgm_read_near to read them). + // Plus, by inlining, all the equations are evaluated at compile-time as everything + // should be a constant. + + FORCEDINLINE void Cmd_Bitmap_Source (const bitmap_info_t& info) {Cmd_Bitmap_Source (info.RAMG_addr);}; + FORCEDINLINE void Cmd_Bitmap_Layout (const bitmap_info_t& info) {Cmd_Bitmap_Layout (info.format, info.linestride, info.height);}; + FORCEDINLINE void Cmd_Bitmap_Size(const bitmap_info_t& info) {Cmd_Bitmap_Size (info.filter, info.wrapx, info.wrapy, info.width, info.height);} + FORCEDINLINE void Cmd_Draw_Button_Icon(int16_t x, int16_t y, int16_t w, int16_t h, const bitmap_info_t& info, const float scale = 1) { + Cmd_Begin(BEGIN_BITMAPS); + if(scale != 1) { + Cmd(BITMAP_TRANSFORM_A | uint32_t(float(256)/scale) & 0xFFFF); + Cmd(BITMAP_TRANSFORM_E | uint32_t(float(256)/scale) & 0xFFFF); + } + Cmd_Bitmap_Size(info.filter, info.wrapx, info.wrapy, info.width*scale, info.height*scale); + Cmd_Vertex_2F((x + w/2 - info.width*scale/2)*16, (y + h/2 - info.height*scale/2)*16); + if(scale != 1) { + Cmd(BITMAP_TRANSFORM_A | 256); + Cmd(BITMAP_TRANSFORM_E | 256); + } + } + template FORCEDINLINE void Cmd_Draw_Button_Text(int16_t x, int16_t y, int16_t w, int16_t h, T text, int16_t font) { + Cmd_Draw_Text(x + w/2, y + h/2, text, font, OPT_CENTER); + } + + void Cmd_Bitmap_Layout (uint8_t format, uint16_t linestride, uint16_t height); + void Cmd_Bitmap_Size(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height); + void Cmd_Bitmap_Handle (uint16_t Handle); + void Cmd_Begin (uint32_t Primitive); + void Cmd_Vertex_2F (uint16_t X_Coord, uint16_t Y_Coord); + void Cmd_Vertex_2II (uint16_t X_Coord, uint16_t Y_Coord, uint8_t B_Handle, uint8_t Cell); + + template void Cmd_Draw_Button(int16_t x, int16_t y, int16_t w, int16_t h, T text, int16_t font, uint16_t option); + template void Cmd_Draw_Text(int16_t x, int16_t y, T text, int16_t font, uint16_t options); + + void Cmd_Draw_Clock (int16_t x, int16_t y, int16_t r, uint16_t option, int16_t h, int16_t m, int16_t s, int16_t ms); + void Cmd_Draw_Progress_Bar (int16_t x, int16_t y, int16_t w, int16_t h, int16_t val, int16_t range); + void Cmd_Draw_Slider (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range); + void Cmd_Mem_Cpy (uint32_t dst, uint32_t src, uint32_t size); + void Cmd_Append (uint32_t ptr, uint32_t size); + }; + + class DLCache { + private: + static uint16_t dl_free; + uint16_t dl_addr = 0; + uint16_t dl_size = 0; + public: + bool hasData(); + void store(); + void append(); + }; + + public: + static void Init (void); + static void Turn_On_Backlight (void); + static void Reset (void); + static void Test_Pulse(void); + static void Enable (void); + static void Disable (void); + static void Set_Backlight (uint16_t Freq, uint8_t Duty); + static void Host_Cmd (unsigned char Host_Command, unsigned char Byte2); + + static void Get_Font_Metrics(uint8_t font, struct FontMetrics &fm); + static void Flash_Write_RGB332_Bitmap(uint32_t Mem_Address, const unsigned char* pRGB332_Array, uint16_t Num_Bytes); + + static uint8_t Get_Tag() {return Mem_Read8(REG_TOUCH_TAG);} +}; + +/********************************* FT800/810 Commands *********************************/ + +#define MULTIPLE_OF_4(val) ((((val)+3)>>2)<<2) + +void CLCD::Enable (void) { + Mem_Write8(REG_PCLK, Pclk); +} + +void CLCD::Disable (void) { + Mem_Write8(REG_PCLK, 0x00); +} + +void CLCD::Set_Backlight (uint16_t Freq, uint8_t Duty) { + Mem_Write16(REG_PWM_HZ, Freq); + Mem_Write8(REG_PWM_DUTY, Duty); +} + +void CLCD::Turn_On_Backlight (void) { + Set_Backlight(0x00FA, 128); +} + +struct FontMetrics { + uint8_t char_widths[128]; + uint32_t font_format; + uint32_t font_stride; + uint32_t font_width; + uint32_t font_height; + uint32_t font_ptr; +}; + +void CLCD::Get_Font_Metrics(uint8_t font, struct FontMetrics &fm) { + Mem_Read_Bulk(ROM_FONT_ADDR + 148 * (font - 16), (uint8_t*) &fm, 148); +} + +// HOST COMMAND FUNCTION + +void CLCD::Host_Cmd (unsigned char Host_Command, unsigned char Byte2) { // Sends 24-Bit Host Command to LCD + if(Host_Command != ACTIVE) { + Host_Command |= 0x40; + } + + spiSelect(); + + spiTransfer(Host_Command); // Write Byte 1 + + spiTransfer(Byte2); // Write Byte 2 + + spiTransfer(0x00); // Write Byte 3 + + spiDeselect(); +} + +void CLCD::Flash_Write_RGB332_Bitmap(uint32_t Mem_Address, const unsigned char* pRGB332_Array, uint16_t Num_Bytes) +{ + unsigned char Flash_Byte; + + for(unsigned int i = 0; i < Num_Bytes; i++) { + Flash_Byte = pgm_read_byte_near(pRGB332_Array + i); + + Mem_Write8((Mem_Address + i), Flash_Byte); + } +} + +uint8_t Device_ID; + +void CLCD::Init (void) { + spiInit(); // Set Up I/O Lines for SPI and FT800/810 Control + delay(50); + + Reset(); // Power Down the FT800/810 for 50 ms + delay(50); + +/* + * If driving the 4D Systems 4DLCD-FT843 Board, the following Init sequence is needed for its FT800 Driver + */ + +#ifdef IS_FT800 // Use External Crystal and 48 MHz System Clock + Host_Cmd(CLKEXT, 0); + + delay(20); + Host_Cmd(CLK48M, 0); +#else + Host_Cmd(CLKINT, 0); + delay(20); + Host_Cmd(CLKSEL, Clksel); // Use Internal RC Oscillator and 48 MHz System Clock +#endif + + delay(20); + + Host_Cmd(ACTIVE, 0); // Activate the System Clock + delay(50); + + delay(400); + Device_ID = Mem_Read8(REG_ID); // Read Device ID, Should Be 0x7C; + #if defined(UI_FRAMEWORK_DEBUG) + if(Device_ID != 0x7C) { + #if defined (SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("Incorrect device ID, should be 7C, got ", Device_ID); + #else + Serial.print(F("Incorrect device ID, should be 7C, got ")); + Serial.println(Device_ID, HEX); + #endif + } else { + #if defined (SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPGM("Device is correct "); + #else + Serial.println(F("Device is correct ")); + #endif + } + #endif + delay(400); + + Mem_Write8(REG_GPIO, 0x00); // Turn OFF Display Enable (GPIO Bit 7); + Mem_Write8(REG_PCLK, 0x00); // Turn OFF LCD PCLK + Set_Backlight(0x00FA, 0); + + /* + * Configure the FT800/810 Registers + */ + + Mem_Write16(REG_HCYCLE, Hcycle); + Mem_Write16(REG_HOFFSET, Hoffset); + Mem_Write16(REG_HSYNC0, Hsync0); + Mem_Write16(REG_HSYNC1, Hsync1); + Mem_Write16(REG_VCYCLE, Vcycle); + Mem_Write16(REG_VOFFSET, Voffset); + Mem_Write16(REG_VSYNC0, Vsync0); + Mem_Write16(REG_VSYNC1, Vsync1); + Mem_Write16(REG_HSIZE, Hsize); + Mem_Write16(REG_VSIZE, Vsize); + Mem_Write8(REG_SWIZZLE, Swizzle); + Mem_Write8(REG_PCLK_POL, Pclkpol); + Mem_Write8(REG_CSPREAD, 1); + + #if defined(LCD_PORTRAIT) && defined(LCD_UPSIDE_DOWN) + Mem_Write8(REG_ROTATE, 3); + #elif defined(LCD_PORTRAIT) && !defined(LCD_UPSIDE_DOWN) + Mem_Write8(REG_ROTATE, 2); + #elif !defined(LCD_PORTRAIT) && defined(LCD_UPSIDE_DOWN) + Mem_Write8(REG_ROTATE, 1); + #else !defined(LCD_PORTRAIT) && !defined(LCD_UPSIDE_DOWN) + Mem_Write8(REG_ROTATE, 0); + #endif + + Mem_Write8(REG_TOUCH_MODE, 0x03); // Configure the Touch Screen + Mem_Write8(REG_TOUCH_ADC_MODE, 0x01); + Mem_Write8(REG_TOUCH_OVERSAMPLE, 0x0F); + Mem_Write16(REG_TOUCH_RZTHRESH, 5000); + Mem_Write8(REG_VOL_SOUND, 0x00); // Turn Synthesizer Volume Off + Mem_Write8(REG_DLSWAP, 0x02); // Swap on New Frame + + /* + * Turn On the Display + */ + #if defined(IS_FT800) + Mem_Write8(REG_GPIO_DIR, 0x80); // Turn ON Display Enable + Mem_Write8(REG_GPIO, 0x80); + #else + Mem_Write16(REG_GPIOX_DIR, 1 << 15); // Turn ON Display Enable + Mem_Write16(REG_GPIOX, 1 << 15); + #endif + + Enable(); // Turns on Clock by setting PCLK Register to 5 + delay(50); + + CommandFifo::Reset(); + delay(50); + + // Set Initial Values for Touch Transform Registers + + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_A, default_transform_a); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_B, default_transform_b); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_C, default_transform_c); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_D, default_transform_d); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_E, default_transform_e); + CLCD::Mem_Write32(REG_TOUCH_TRANSFORM_F, default_transform_f); +} + +/******************* FT800/810 Graphic Commands *********************************/ + +inline uint32_t CLCD::pack_rgb(uint8_t r, uint8_t g, uint8_t b) { + return (uint32_t(r) << 16) | (uint32_t(g) << 8) | uint32_t(b); +} + +void CLCD::CommandFifo::Cmd_Clear_Color (uint32_t rgb) // DL Command - Set Clear Screen Color +{ + Cmd(CLEAR_COLOR_RGB | rgb); +} + +void CLCD::CommandFifo::Cmd_Clear (bool Clr, bool Stl, bool Tag) // DL Command - Clear Color-Stencil-Tag Buffer(s) +{ + Cmd( CLEAR | + (Clr ? 0b00000001 : 0) | + (Stl ? 0b00000010 : 0) | + (Tag ? 0b00000100 : 0) + ); +} + +void CLCD::CommandFifo::Cmd_Color (uint32_t rgb) // DL Command - Set Current Color +{ + Cmd(COLOR_RGB | rgb); +} + +void CLCD::CommandFifo::Cmd_Set_Foreground_Color (uint32_t rgb) // Co-Processor Command - Set Foreground Color for Widgets +{ + Cmd(CMD_FGCOLOR); + Cmd(rgb); +} + +void CLCD::CommandFifo::Cmd_Set_Background_Color (uint32_t rgb) // Co-Processor Command - Set Background Color for Widgets +{ + Cmd(CMD_BGCOLOR); + Cmd(rgb); +} + +void CLCD::CommandFifo::Cmd_Set_Tag (uint8_t Tag) +{ + Cmd(TAG | Tag); +} + +void CLCD::CommandFifo::Cmd_Bitmap_Source (uint32_t RAM_G_Addr) +{ + Cmd(BITMAP_SOURCE | (RAM_G_Addr & 0x000FFFFF)); +} + +void CLCD::CommandFifo::Cmd_Bitmap_Layout (uint8_t format, uint16_t linestride, uint16_t height) +{ + Cmd( BITMAP_LAYOUT | + (uint32_t(height) << 0) | + (uint32_t(linestride) << 9) | + (uint32_t(format) << 19) + ); +} + +void CLCD::CommandFifo::Cmd_Bitmap_Size(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height) +{ + Cmd( BITMAP_SIZE | + (uint32_t(height) << 0) | + (uint32_t(width) << 9) | + (uint32_t(wrapy) << 18) | + (uint32_t(wrapx) << 19) | + (uint32_t(filter) << 20) + ); +} + +void CLCD::CommandFifo::Cmd_Bitmap_Handle (uint16_t Handle) +{ + Cmd( BITMAP_HANDLE | Handle); +} + + +void CLCD::CommandFifo::Cmd_Begin (uint32_t Primitive) +{ + Cmd(BEGIN + Primitive); +} + +void CLCD::CommandFifo::Cmd_Vertex_2II (uint16_t X_Coord, uint16_t Y_Coord, uint8_t B_Handle, uint8_t Cell) +{ + Cmd( VERTEX2II | + (uint32_t(Cell) << 0) | + (uint32_t(B_Handle) << 7) | + (uint32_t(Y_Coord) << 12) | + (uint32_t(X_Coord) << 21) + ); +} + +void CLCD::CommandFifo::Cmd_Vertex_2F (uint16_t X_Coord, uint16_t Y_Coord) +{ + Cmd( VERTEX2F | + (uint32_t(Y_Coord) << 0) | + (uint32_t(X_Coord) << 15) + ); +} + +template void CLCD::CommandFifo::Cmd_Draw_Button(int16_t x, int16_t y, int16_t w, int16_t h, T text, int16_t font, uint16_t option) +{ + struct { + int32_t type = CMD_BUTTON; + int16_t x; + int16_t y; + int16_t w; + int16_t h; + int16_t font; + uint16_t option; + } cmd_data; + + cmd_data.x = x; + cmd_data.y = y; + cmd_data.w = w; + cmd_data.h = h; + cmd_data.font = font; + cmd_data.option = option; + + Cmd( &cmd_data, sizeof(cmd_data) ); + Cmd_Str(text); +} + +template void CLCD::CommandFifo::Cmd_Draw_Text(int16_t x, int16_t y, T text, int16_t font, uint16_t options) +{ + struct { + int32_t type = CMD_TEXT; + int16_t x; + int16_t y; + int16_t font; + uint16_t options; + } cmd_data; + + cmd_data.x = x; + cmd_data.y = y; + cmd_data.font = font; + cmd_data.options = options; + + Cmd( &cmd_data, sizeof(cmd_data) ); + Cmd_Str(text); +} + +void CLCD::CommandFifo::Cmd_Draw_Clock (int16_t x, int16_t y, int16_t r, uint16_t option, int16_t h, int16_t m, int16_t s, int16_t ms) +{ + struct { + int32_t type = CMD_CLOCK; + int16_t x; + int16_t y; + int16_t r; + uint16_t option; + int16_t h; + int16_t m; + int16_t s; + int16_t ms; + } cmd_data; + + cmd_data.x = x; + cmd_data.y = y; + cmd_data.r = r; + cmd_data.option = option; + cmd_data.h = h; + cmd_data.m = m; + cmd_data.s = s; + cmd_data.ms = ms; + + Cmd( &cmd_data, sizeof(cmd_data) ); +} + +void CLCD::CommandFifo::Cmd_Draw_Progress_Bar (int16_t x, int16_t y, int16_t w, int16_t h, int16_t val, int16_t range) +{ + struct { + int32_t type = CMD_PROGRESS; + int16_t x; + int16_t y; + int16_t w; + uint16_t h; + uint16_t val; + uint16_t range; + } cmd_data; + + cmd_data.x = x; + cmd_data.y = y; + cmd_data.w = w; + cmd_data.h = h; + cmd_data.val = val; + cmd_data.range = range; + + Cmd( &cmd_data, sizeof(cmd_data) ); +} + +void CLCD::CommandFifo::Cmd_Draw_Slider (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range) +{ + struct { + int32_t type = CMD_SLIDER; + int16_t x; + int16_t y; + int16_t w; + int16_t h; + uint16_t options; + uint16_t val; + uint16_t range; + } cmd_data; + + cmd_data.x = x; + cmd_data.y = y; + cmd_data.w = w; + cmd_data.h = h; + cmd_data.options = options; + cmd_data.val = val; + cmd_data.range = range; + + Cmd( &cmd_data, sizeof(cmd_data) ); +} + +void CLCD::CommandFifo::Cmd_Mem_Cpy (uint32_t dst, uint32_t src, uint32_t size) +{ + struct { + uint32_t type = CMD_MEMCPY; + uint32_t dst; + uint32_t src; + uint32_t size; + } cmd_data; + + cmd_data.dst = dst; + cmd_data.src = src; + cmd_data.size = size; + + Cmd( &cmd_data, sizeof(cmd_data) ); +} + +void CLCD::CommandFifo::Cmd_Append (uint32_t ptr, uint32_t size) +{ + struct { + uint32_t type = CMD_APPEND; + uint32_t ptr; + uint32_t size; + } cmd_data; + + cmd_data.ptr = ptr; + cmd_data.size = size; + + Cmd( &cmd_data, sizeof(cmd_data) ); +} + +/******************* DISPLAY LIST CACHE MANAGEMENT ************************/ + +/* The Display List Cache mechanism stores the display list corresponding + * to a menu into RAM_G so that on subsequent calls drawing the menu does + * not require as much SPI traffic. Dynamic content, such as indicators, + * should not be cached. + * + * The DLCache can be used like so: + * + * void some_function() { + * static CLCD::DLCache dlcache; + * + * if(dlcache.hasData()) { + * dlcache.append(); + * } else { + * // Add stuff to the DL + * dlcache.store(); + * } + */ + +uint16_t CLCD::DLCache::dl_free = DL_CACHE_START; + +bool CLCD::DLCache::hasData() { + return dl_addr != 0; +} + +void CLCD::DLCache::store() { + while(!CommandFifo::Is_Idle()); + + dl_size = Mem_Read32(REG_CMD_DL) & 0x07FF; + dl_addr = dl_free; + + if((dl_addr + dl_size) > (1024*1024)) { + // Not enough memory to cache the display list. + dl_addr = 0; + } else { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd_Mem_Cpy(RAM_G + dl_addr, RAM_DL, dl_size); + cmd.Cmd_Execute(); + dl_free += dl_size; + } +} + +void CLCD::DLCache::append() { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd_Append(RAM_G + dl_addr, dl_size); + cmd.Cmd_Execute(); +} + +#endif // _AO_FT810_FUNC_H + + + + + diff --git a/Marlin/AO_FT810_Pins.h b/Marlin/AO_FT810_Pins.h new file mode 100644 index 000000000..d21642892 --- /dev/null +++ b/Marlin/AO_FT810_Pins.h @@ -0,0 +1,53 @@ +/** + * Pins for the Aleph Objects Color LCD Touchscreen. + * + * Marlin 3D Printer Firmware + * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#if defined(LULZBOT_Quiver_TAZ7_CLCD) // ARCHIM J20 HEADER +3.3V Pin-24 GND Pin-23 + #define CLCD_BB_SPI_CS 99 // PB6 J20 Pin-9 + #define CLCD_BB_SPI_SCLK 95 // PB0 J20 Pin-6 + #define CLCD_BB_SPI_MOSI 94 // PB1 J20 Pin-5 + #define CLCD_BB_SPI_MISO 101 // PB5 J20 Pin-10 + #define CLCD_MOD_RESET 93 // PB2 J20 Pin-8 +#endif + +#if defined(LULZBOT_Gladiola_Mini_CLCD) // MINI RAMBO P1 HEADER +5V Pin-10 GND Pin-9 + #define CLCD_BB_SPI_SCLK 71 // PG3 P1 Pin-8 + #define CLCD_BB_SPI_MOSI 85 // PH7 P1 Pin-7 + #define CLCD_BB_SPI_CS 70 // PG4 P1 Pin-6 + #define CLCD_MOD_RESET 19 // PD2 P1 Pin-5 + #define CLCD_BB_SPI_MISO 82 // PD5 P1 Pin-4 + #define CLCD_AUX_0 18 // PD3 P1 Pin-3 + #define CLCD_AUX_1 9 // PH6 P1 Pin-2 + #define CLCD_AUX_2 84 // PH2 P1 Pin-1 +#endif + +#if defined(LULZBOT_Hibiscus_Mini2_CLCD) // EINSY P1 HEADER +5V Pin-1 GND Pin-2 + #define CLCD_BB_SPI_SCLK 71 // PG3 P1 Pin-3 + #define CLCD_BB_SPI_MOSI 85 // PH7 P1 Pin-4 + #define CLCD_BB_SPI_CS 70 // PG4 P1 Pin-5 + #define CLCD_MOD_RESET 19 // PD2 P1 Pin-6 + #define CLCD_BB_SPI_MISO 82 // PD5 P1 Pin-7 + #define CLCD_AUX_0 18 // PD3 P1 Pin-8 + #define CLCD_AUX_1 9 // PH6 P1 Pin-9 + #define CLCD_AUX_2 84 // PH2 P1 Pin-10 +#endif \ No newline at end of file diff --git a/Marlin/AO_FT810_SPI.h b/Marlin/AO_FT810_SPI.h new file mode 100644 index 000000000..b2c67adfe --- /dev/null +++ b/Marlin/AO_FT810_SPI.h @@ -0,0 +1,387 @@ +/********************* + * FT810_SPI.h * + *********************/ + + +/**************************************************************************** + * Written By Mark Pelletier 2017 - Aleph Objects, Inc. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * To view a copy of the GNU General Public License, go to the following * + * location: . * + ****************************************************************************/ +#ifndef _AO_FT810_SPI_H +#define _AO_FT810_SPI_H + +#if defined(PIN_DIR_OUT) + // If SET_OUTPUT is defined, then map Marlin routines to those + #define SET_OUTPUT PIN_DIR_OUT + #define SET_INPUT_PULLUP(a) _PIN_DIR_IN(a); _PIN_HIGH(a); + #define SET_INPUT PIN_DIR_IN + #define WRITE SET_PIN + #define READ GET_PIN +#endif + +/********************************* SPI Functions *********************************/ + +void CLCD::spiInit (void) { +#if defined(USE_ARDUINO_HW_SPI) + SPI.begin(); + SPI.beginTransaction(LCDsettings); +#else + SET_OUTPUT(CLCD_MOD_RESET); // CLCD_MOD_RST - Module Reset, not SPI + WRITE(CLCD_MOD_RESET, 1); + + SET_OUTPUT(CLCD_BB_SPI_MOSI); // CLCD_MOSI + WRITE(CLCD_BB_SPI_MOSI, 1); + + SET_OUTPUT(CLCD_BB_SPI_SCLK); // CLCD_SCLK + WRITE(CLCD_BB_SPI_SCLK, 0); + + SET_OUTPUT(CLCD_BB_SPI_CS); // CLCD_CS + WRITE(CLCD_BB_SPI_CS, 1); + + SET_INPUT_PULLUP(CLCD_BB_SPI_MISO); // CLCD_MISO + + delay(50); +#endif +} + +void CLCD::spiSelect (void) { // CLCD Bitbanged SPI - Chip Select + WRITE(CLCD_BB_SPI_CS, 0); +} + + +void CLCD::spiDeselect (void) { // CLCD Bitbanged SPI - Chip Deselect + WRITE(CLCD_BB_SPI_CS, 1); +} + +void CLCD::Reset (void) { + WRITE(CLCD_MOD_RESET, 0); + delay(50); + WRITE(CLCD_MOD_RESET, 1); +} + +void CLCD::Test_Pulse(void) +{ + WRITE(CLCD_AUX_0, 1); + delayMicroseconds(10); + WRITE(CLCD_AUX_0, 0); +} + +uint8_t CLCD::spiTransfer (uint8_t spiOutByte) { +#ifdef IS_ARDUINO + SPI.transfer(spiOutByte); +#else + + uint8_t spiIndex = 0x80; + uint8_t spiInByte = 0; + uint8_t k; + + for(k = 0; k <8; k++) { // Output and Read each bit of spiOutByte and spiInByte + if(spiOutByte & spiIndex) { // Output MOSI Bit + WRITE(CLCD_BB_SPI_MOSI, 1); + } + else { + WRITE(CLCD_BB_SPI_MOSI, 0); + } + WRITE(CLCD_BB_SPI_SCLK, 1); // Pulse Clock + WRITE(CLCD_BB_SPI_SCLK, 0); + + if(READ(CLCD_BB_SPI_MISO)) { + spiInByte |= spiIndex; + } + + spiIndex >>= 1; + } + return spiInByte; +#endif +} + +// MEMORY READ FUNCTIONS + +void CLCD::Mem_ReadAddr (uint32_t Reg_Address) { // Write 4-Byte Address + CLCD::spiTransfer((Reg_Address >> 16) & 0x3F); // Address [21:16] + CLCD::spiTransfer((Reg_Address >> 8 ) & 0xFF); // Address [15:8] + CLCD::spiTransfer((Reg_Address >> 0) & 0xFF); // Address [7:0] + CLCD::spiTransfer(0x00); // Dummy Byte +} + +void CLCD::Mem_Read_Bulk (uint32_t Reg_Address, uint8_t *Data, uint16_t Len) { // Write 4-Byte Address, Read Multiple Bytes + CLCD::spiSelect(); + CLCD::Mem_ReadAddr(Reg_Address); + + while(Len--) { + *Data = CLCD::spiTransfer(0x00); // Read 1 Byte + *Data++; + } + + CLCD::spiDeselect(); +} + +uint8_t CLCD::Mem_Read8 (uint32_t Reg_Address) { // Write 4-Byte Address, Read 1-Byte Data + CLCD::spiSelect(); + + CLCD::Mem_ReadAddr(Reg_Address); + + uint8_t R_Data = CLCD::spiTransfer(0x00); // Read 1 Byte + + CLCD::spiDeselect(); + + return(R_Data); +} + + +uint16_t CLCD::Mem_Read16 (uint32_t Reg_Address) { // Write 4-Byte Address, Read 2-Bytes Data + CLCD::spiSelect(); + + CLCD::Mem_ReadAddr(Reg_Address); + + uint16_t R_Data = (((uint16_t) CLCD::spiTransfer(0x00)) << 0) | // Read Byte 1 + (((uint16_t) CLCD::spiTransfer(0x00)) << 8); // Read Byte 2 + + CLCD::spiDeselect(); + + return(R_Data); +} + +uint32_t CLCD::Mem_Read32 (uint32_t Reg_Address) { // Write 4-Byte Address, Read 4-Bytes Data + CLCD::spiSelect(); + + CLCD::Mem_ReadAddr(Reg_Address); + + uint32_t R_Data = (((uint32_t) CLCD::spiTransfer(0x00)) << 0) | // Read Byte 1 + (((uint32_t) CLCD::spiTransfer(0x00)) << 8) | // Read Byte 2 + (((uint32_t) CLCD::spiTransfer(0x00)) << 16) | // Read Byte 3 + (((uint32_t) CLCD::spiTransfer(0x00)) << 24); // Read Byte 4 + + CLCD::spiDeselect(); + + return(R_Data); +} + + +// MEMORY WRITE FUNCTIONS + +void CLCD::Mem_WriteAddr (uint32_t Reg_Address) { // Write 3-Byte Address + CLCD::spiTransfer((Reg_Address >> 16) | 0x80); // Address [21:16] + CLCD::spiTransfer((Reg_Address >> 8 ) & 0xFF); // Address [15:8] + CLCD::spiTransfer((Reg_Address >> 0) & 0xFF); // Address [7:0] +} + +void CLCD::Mem_Write_Bulk (uint32_t Reg_Address, const void *Data, uint16_t Len, uint8_t Padding) { // Write 3-Byte Address, Multiple Bytes, plus padding bytes + const uint8_t* p = (const uint8_t *)Data; + CLCD::spiSelect(); + CLCD::Mem_WriteAddr(Reg_Address); + + while(Len--) { + CLCD::spiTransfer(*p++); // Write 1 Byte + } + + while(Padding--) { + CLCD::spiTransfer(0); // Padding Bytes + } + + CLCD::spiDeselect(); +} + +void CLCD::Mem_Write_Bulk (uint32_t Reg_Address, progmem_str Str, uint16_t Len, uint8_t Padding) { // Write 3-Byte Address, Multiple Bytes, plus padding bytes + const uint8_t* p = (const uint8_t *)Str; + CLCD::spiSelect(); + CLCD::Mem_WriteAddr(Reg_Address); + + while(Len--) { + CLCD::spiTransfer(pgm_read_byte_near(p++)); // Write 1 Byte + } + + while(Padding--) { + CLCD::spiTransfer(0); // Padding Bytes + } + + CLCD::spiDeselect(); +} + +void CLCD::Mem_Write8 (uint32_t Reg_Address, uint8_t W_Data) { // Write 3-Byte Address, Write 1-Byte Data + CLCD::spiSelect(); + + CLCD::Mem_WriteAddr(Reg_Address); + + CLCD::spiTransfer(W_Data); // Write 1 Byte + + CLCD::spiDeselect(); +} + + +void CLCD::Mem_Write16 (uint32_t Reg_Address, uint16_t W_Data) { // Write 3-Byte Address, Write 2-Bytes Data + CLCD::spiSelect(); + + CLCD::Mem_WriteAddr(Reg_Address); + + CLCD::spiTransfer((uint8_t) ((W_Data >> 0) & 0x00FF)); // Write Byte 0 + CLCD::spiTransfer((uint8_t) ((W_Data >> 8) & 0x00FF)); // Write Byte 1 + + CLCD::spiDeselect(); +} + + +void CLCD::Mem_Write32 (uint32_t Reg_Address, uint32_t W_Data) { // Write 3-Byte Address, Write 4-Bytes Data + CLCD::spiSelect(); + + CLCD::Mem_WriteAddr(Reg_Address); + + CLCD::spiTransfer(W_Data >> 0); // Write Byte 0 + CLCD::spiTransfer(W_Data >> 8); // Write Byte 1 + CLCD::spiTransfer(W_Data >> 16); // Write Byte 2 + CLCD::spiTransfer(W_Data >> 24); // Write Byte 3 + + CLCD::spiDeselect(); +} + +/**************************** FT800/810 Co-Processor Command FIFO ****************************/ + +uint32_t CLCD::CommandFifo::getRegCmdWrite() { + return Mem_Read32(REG_CMD_WRITE) & 0x0FFF; +} + +uint32_t CLCD::CommandFifo::getRegCmdRead() { + return Mem_Read32(REG_CMD_READ) & 0x0FFF; +} + +bool CLCD::CommandFifo::Is_Idle() { + return getRegCmdRead() == getRegCmdWrite(); +} + +void CLCD::CommandFifo::Wait_Until_Idle() { + do { + } while(!Is_Idle()); +} + +#if defined(IS_FT800) +void CLCD::CommandFifo::Start() { + command_write_ptr = getRegCmdWrite(); +} + +void CLCD::CommandFifo::Execute() { + Mem_Write32(REG_CMD_WRITE, command_write_ptr); +} + +void CLCD::CommandFifo::Reset() { + Mem_Write32(REG_CMD_WRITE, 0x00000000); + Mem_Write32(REG_CMD_READ, 0x00000000); + command_write_ptr = 0; +}; + +template void CLCD::CommandFifo::_write_unaligned(T data, uint16_t len) { + const char *ptr = (const char*)data; + uint32_t bytes_tail, bytes_head; + uint32_t command_read_ptr; + + /* Wait until there is enough space in the circular buffer for the transfer */ + do { + command_read_ptr = getRegCmdRead(); + if (command_read_ptr <= command_write_ptr) { + bytes_tail = 4096U - command_write_ptr; + bytes_head = command_read_ptr; + } else { + bytes_tail = command_read_ptr - command_write_ptr; + bytes_head = 0; + } + } while((bytes_tail + bytes_head) < len); + + /* Write as many bytes as possible following REG_CMD_WRITE */ + uint16_t bytes_to_write = min(len, bytes_tail); + Mem_Write_Bulk (RAM_CMD + command_write_ptr, T(ptr), bytes_to_write); + command_write_ptr += bytes_to_write; + ptr += bytes_to_write; + len -= bytes_to_write; + + if(len > 0) { + /* Write remaining bytes at start of circular buffer */ + Mem_Write_Bulk (RAM_CMD, T(ptr), len); + command_write_ptr = len; + } + + if(command_write_ptr == 4096U) { + command_write_ptr = 0; + } +} + +// Writes len bytes into the FIFO, if len is not +// divisible by four, zero bytes will be written +// to align to the boundary. + +template void CLCD::CommandFifo::write(T data, uint16_t len) { + const uint8_t padding = MULTIPLE_OF_4(len) - len; + + uint8_t pad_bytes[] = {0, 0, 0, 0}; + _write_unaligned(data, len); + _write_unaligned(pad_bytes, padding); +} +#else +uint32_t CLCD::CommandFifo::getRegCmdBSpace() { + return Mem_Read32(REG_CMDB_SPACE) & 0x0FFF; +} + +void CLCD::CommandFifo::Cmd_Start() { +} + +void CLCD::CommandFifo::Cmd_Execute() { +} + +void CLCD::CommandFifo::Reset() { + Mem_Write32(REG_CMD_WRITE, 0x00000000); + Mem_Write32(REG_CMD_READ, 0x00000000); +}; + +// Writes len bytes into the FIFO, if len is not +// divisible by four, zero bytes will be written +// to align to the boundary. + +template void CLCD::CommandFifo::write(T data, uint16_t len) { + const uint8_t padding = MULTIPLE_OF_4(len) - len; + + // The FT810 provides a special register that can be used + // for writing data without us having to do our own FIFO + // management. + uint32_t Command_Space = getRegCmdBSpace(); + while(Command_Space < len + padding) { + Command_Space = getRegCmdBSpace(); + } + Mem_Write_Bulk(REG_CMDB_WRITE, data, len, padding); +} +#endif + +// CO_PROCESSOR COMMANDS + +void CLCD::CommandFifo::Cmd (uint32_t cmd32) { // Writes a 32-bit (4 Bytes) Value to the Co-processor Command Buffer FIFO + write(&cmd32, sizeof(uint32_t)); +} + +void CLCD::CommandFifo::Cmd (void* data, uint16_t len) { // Writes a data structure - always a multiple of 32 bits - to the Co_Processor FIFO. // Data structure includes the 32-bit Co_Processor command. + write(data, len); +} + + +void CLCD::CommandFifo::Cmd_Str (char* data) { + write(data, strlen(data)+1); +} + +void CLCD::CommandFifo::Cmd_Str (progmem_str data) { + write(data, strlen_P((const char*)data)+1); +} + +#endif // _AO_FT810_SPI_H + + + + + diff --git a/Marlin/AO_FT810_UI_Bitmaps.h b/Marlin/AO_FT810_UI_Bitmaps.h new file mode 100644 index 000000000..11aab1532 --- /dev/null +++ b/Marlin/AO_FT810_UI_Bitmaps.h @@ -0,0 +1,177 @@ +/*************************** + * AO_FT810_Menu_Bitmaps.h * + ***************************/ + +/**************************************************************************** + * Written By Mark Pelletier 2017 - Aleph Objects, Inc. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * To view a copy of the GNU General Public License, go to the following * + * location: . * + ****************************************************************************/ + + +// Colors RGB332 + +#define COLOR0 0x00 // Black +#define COLOR1 0x49 // Gray +#define COLOR2 0x7C // Yellow Green +#define COLOR3 0xFF // White + +// L1 Font Data for Widgets + +const PROGMEM CLCD::bitmap_info_t Extruder_Icon_Info = { + .format = L1, + .linestride = 3, + .filter = BILINEAR, + .wrapx = BORDER, + .wrapy = BORDER, + .RAMG_addr = RAM_G + 8000, + .width = 24, + .height = 23, +}; + +const PROGMEM unsigned char Extruder_Icon[] = {0x3F, 0xFF, 0xFC, + 0x7F, 0xFF, 0xFE, + 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x03, + 0x7F, 0xFF, 0xFE, + 0x3F, 0xFF, 0xFC, + 0x3F, 0xFF, 0xFC, + 0x7F, 0xFF, 0xFE, + 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x03, + 0x7F, 0xFF, 0xFE, + 0x7F, 0xFF, 0xFE, + 0x07, 0xFF, 0xE0, + 0x03, 0xFF, 0xC0, + 0x01, 0x81, 0x80, + 0x00, 0xC3, 0x00, + 0x00, 0x66, 0x00, + 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00}; + +const PROGMEM CLCD::bitmap_info_t Bed_Heat_Icon_Info = { + .format = L1, + .linestride = 4, + .filter = BILINEAR, + .wrapx = BORDER, + .wrapy = BORDER, + .RAMG_addr = RAM_G + 8100, + .width = 32, + .height = 23, +}; + +const PROGMEM unsigned char Bed_Heat_Icon[] = {0x01, 0x81, 0x81, 0x80, + 0x01, 0x81, 0x81, 0x80, + 0x00, 0xC0, 0xC0, 0xC0, + 0x00, 0xC0, 0xC0, 0xC0, + 0x00, 0x60, 0x60, 0x60, + 0x00, 0x60, 0x60, 0x60, + 0x00, 0xC0, 0xC0, 0xC0, + 0x00, 0xC0, 0xC0, 0xC0, + 0x01, 0x81, 0x81, 0x80, + 0x01, 0x81, 0x81, 0x80, + 0x03, 0x03, 0x03, 0x00, + 0x03, 0x03, 0x03, 0x00, + 0x06, 0x06, 0x06, 0x00, + 0x06, 0x06, 0x06, 0x00, + 0x03, 0x03, 0x03, 0x00, + 0x03, 0x03, 0x03, 0x00, + 0x01, 0x81, 0x81, 0x80, + 0x01, 0x81, 0x81, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xC0, 0x00, 0x00, 0x03, + 0xFF, 0xFF, 0xFF, 0xFF}; + +const PROGMEM CLCD::bitmap_info_t Fan_Icon_Info = { + .format = L1, + .linestride = 4, + .filter = BILINEAR, + .wrapx = BORDER, + .wrapy = BORDER, + .RAMG_addr = RAM_G + 8300, + .width = 32, + .height = 32, +}; + +const PROGMEM unsigned char Fan_Icon[] = {0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xF8, 0x00, 0x00, 0x1F, + 0xF0, 0x03, 0xF8, 0x0F, + 0xE0, 0x07, 0xF0, 0x07, + 0xC0, 0x0F, 0xE0, 0x03, + 0xC0, 0x1F, 0xE0, 0x03, + 0xC0, 0x1F, 0xE0, 0x03, + 0xC0, 0x0F, 0xE0, 0x03, + 0xC0, 0x07, 0xE0, 0x03, + 0xC0, 0x03, 0xC0, 0x03, + 0xD0, 0x00, 0x00, 0xC3, + 0xD8, 0x03, 0xC1, 0xE3, + 0xDF, 0xC7, 0xE3, 0xF3, + 0xDF, 0xEF, 0xF7, 0xFB, + 0xDF, 0xEF, 0xF7, 0xFB, + 0xDF, 0xEF, 0xF7, 0xFB, + 0xDF, 0xEF, 0xF7, 0xFB, + 0xCF, 0xC7, 0xE3, 0xFB, + 0xC7, 0x83, 0xC0, 0x1B, + 0xC3, 0x00, 0x00, 0x0B, + 0xC0, 0x03, 0xC0, 0x03, + 0xC0, 0x07, 0xE0, 0x03, + 0xC0, 0x07, 0xF0, 0x03, + 0xC0, 0x07, 0xF8, 0x03, + 0xC0, 0x07, 0xF8, 0x03, + 0xC0, 0x07, 0xF0, 0x03, + 0xE0, 0x0F, 0xE0, 0x07, + 0xF0, 0x1F, 0xC0, 0x0F, + 0xF8, 0x00, 0x00, 0x1F, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF}; + + +const PROGMEM CLCD::bitmap_info_t TD_Icon_Info = { + .format = L1, + .linestride = 7, + .filter = BILINEAR, + .wrapx = BORDER, + .wrapy = BORDER, + .RAMG_addr = RAM_G + 8400, + .width = 50, + .height = 20, +}; + +const PROGMEM unsigned char TD_Icon[] = {0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, // Thumb Drive Widget + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x80, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x80, + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00}; diff --git a/Marlin/AO_FT810_UI_Screens.h b/Marlin/AO_FT810_UI_Screens.h new file mode 100644 index 000000000..291b961d5 --- /dev/null +++ b/Marlin/AO_FT810_UI_Screens.h @@ -0,0 +1,1197 @@ +/**************************************************************************** + * Written By Mark Pelletier 2018 - Aleph Objects, Inc. * + * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * To view a copy of the GNU General Public License, go to the following * + * location: . * + ****************************************************************************/ + +#define STATUS_MESSAGE_BUFFER_LENGTH 32 +char lcd_status_message[STATUS_MESSAGE_BUFFER_LENGTH] = WELCOME_MSG; + +static float marlin_x_axis = 100; +static float marlin_y_axis = 50; +static float marlin_z_axis = 170; +static int marlin_e0_temp = 25; +static int marlin_e1_temp = 25; +static int marlin_bed_temp = 25; +static int marlin_fan_speed = 25; +static float marlin_x_steps = 100; +static float marlin_y_steps = 100; +static float marlin_z_steps = 100; +static float marlin_e0_steps = 100; +static float marlin_z_offset = 0.150; + +/**************************** GRID LAYOUT MACROS **************************/ + +/* The grid layout macros allow buttons to be arranged on a grid so + * that their locations become independent of the display size. The + * layout model is similar to that of HTML TABLEs. + * + * These macros are meant to be evaluated into constants at compile + * time, so resolution independence can be as efficient as using + * hard-coded coordinates. + */ + +// Margin defines the margin (in pixels) on each side of a button in +// the layout + +#define MARGIN_L 5 +#define MARGIN_R 5 +#define MARGIN_T 5 +#define MARGIN_B 5 + +// EDGE_R adds some black space on the right edge of the display +// This shifts some of the screens left to visually center them. + +#define EDGE_R 0 + +// GRID_X and GRID_Y computes the positions of the divisions on +// the layout grid. +#if defined(LCD_PORTRAIT) +#define GRID_X(x) ((x)*(Vsize-EDGE_R)/GRID_COLS) +#define GRID_Y(y) ((y)*Hsize/GRID_ROWS) +#else +#define GRID_X(x) ((x)*(Hsize-EDGE_R)/GRID_COLS) +#define GRID_Y(y) ((y)*Vsize/GRID_ROWS) +#endif + +// BTN_X, BTN_Y, BTN_W and BTN_X returns the top-left and width +// and height of a button, taking into account the button margins. + +#define BTN_X(x) (GRID_X(x-1) + MARGIN_L) +#define BTN_Y(y) (GRID_Y(y-1) + MARGIN_T) +#define BTN_W(w) (GRID_X(w) - MARGIN_L - MARGIN_R) +#define BTN_H(h) (GRID_Y(h) - MARGIN_T - MARGIN_B) + +// Abbreviations for common phrases, to allow a button to be +// defined in one line of source. +#define BTN_POS(x,y) BTN_X(x), BTN_Y(y) +#define BTN_SIZE(w,h) BTN_W(w), BTN_H(h) +#define BTN cmd.Cmd_Draw_Button +#define BTX cmd.Cmd_Draw_Button_Text +#define BTI cmd.Cmd_Draw_Button_Icon +#define BTN_TAG(t) cmd.Cmd_Set_Tag(t); +#define RGB(rgb) cmd.Cmd_Set_Foreground_Color(Theme::rgb); +#define TOGGLE(val) cmd.Cmd_Set_Foreground_Color(val ? Theme::toggle_on : Theme::toggle_off); + +#define FONT_SML Theme::font_small +#define FONT_MED Theme::font_medium +#define FONT_LRG Theme::font_large + +#define MENU_BTN_STYLE Theme::font_medium, OPT_3D + +/************************* MENU SCREEN DECLARATIONS *************************/ + +class BootScreen : public UIScreen { + public: + static void onRefresh(); + static void onIdle(); +}; + +class AboutScreen : public UIScreen { + private: + static void playChime(); + static void draw(bool); + public: + static void onEntry(); + static void onRefresh(); + static void onTouchStart(uint8_t tag); +}; + +class StatusScreen : public UIScreen { + public: + static void onRefresh(); + static void onStartup(); + static void onEntry(); + static void onIdle(); + static void onTouchStart(uint8_t tag); +}; + +class MenuScreen : public UIScreen { + public: + static void onRefresh(); + static void onTouchStart(uint8_t tag); +}; + +class CalibrationScreen : public UIScreen { + public: + static void onRefresh(); + static void onIdle(); +}; + +class CalibrationRegistersScreen : public UIScreen { + public: + static void onRefresh(); + static void onTouchStart(uint8_t tag); +}; + +class AdvancedSettingsScreen : public UIScreen { + public: + static void onRefresh(); + static void onTouchStart(uint8_t tag); +}; + +class ValueAdjusters : public UIScreen { + protected: + static float increment; + static void static_heading(progmem_str heading); + static void static_value(int line, progmem_str value); + static void dynamic_value(int line, float value, progmem_str units); + public: + static void onTouchStart(uint8_t tag); +}; + +class MoveAxisScreen : public ValueAdjusters { + public: + static void onRefresh(); + static void onTouchHeld(uint8_t tag); +}; + +class StepsScreen : public ValueAdjusters { + public: + static void onRefresh(); + static void onTouchHeld(uint8_t tag); +}; + +class ZOffsetScreen : public ValueAdjusters { + public: + static void onRefresh(); + static void onTouchHeld(uint8_t tag); +}; + +class TemperatureScreen : public ValueAdjusters { + public: + static void onRefresh(); + static void onTouchHeld(uint8_t tag); +}; + +/******************************* MENU SCREEN TABLE ******************************/ + +SCREEN_TABLE { + DECL_SCREEN(BootScreen), + DECL_SCREEN(AboutScreen), + DECL_SCREEN(CalibrationScreen), + DECL_SCREEN(StatusScreen), + DECL_SCREEN(MenuScreen), + DECL_SCREEN(MoveAxisScreen), + DECL_SCREEN(AdvancedSettingsScreen), + DECL_SCREEN(StepsScreen), + DECL_SCREEN(ZOffsetScreen), + DECL_SCREEN(TemperatureScreen), + DECL_SCREEN(CalibrationRegistersScreen) +}; + +SCREEN_TABLE_POST + +/************************************ MENU THEME ********************************/ + +namespace Theme { + const uint32_t olive_darkest = 0x2A2F0A; + const uint32_t olive_dark = 0x495212; + const uint32_t olive_light = 0x8C9D22; + + const uint32_t background = 0x707070; + const uint32_t x_axis = 0x500000; + const uint32_t y_axis = 0x005000; + const uint32_t z_axis = 0x000050; + const uint32_t e_axis = 0x000000; + const uint32_t menu_btn = olive_dark; + const uint32_t navi_btn = olive_light; + + const uint32_t toggle_on = olive_light; + const uint32_t toggle_off = olive_darkest; + const uint32_t disabled = background; + + // About screen + const uint32_t about_bg = olive_dark; + const uint32_t about_btn = olive_darkest; + + // Adjustment Screens + + const uint32_t adjust_bg = olive_dark; + const uint32_t incr_btn = olive_darkest; + + // Status screen + const uint32_t stop_btn = 0xF02020; + const uint32_t prnt_btn = 0x20D020; + const uint32_t progress = 0x404040; + const uint32_t status_msg = 0x404040; + const uint32_t fan_speed = 0x6060D0; + const uint32_t temp = 0xD04000; + const uint32_t axis_label = 0x404040; + + // Calibration Registers Screen + const uint32_t transformA = 0x3010D0; + const uint32_t transformB = 0x4010D0; + const uint32_t transformC = 0x5010D0; + const uint32_t transformD = 0x6010D0; + const uint32_t transformE = 0x7010D0; + const uint32_t transformF = 0x8010D0; + const uint32_t transformVal = 0x104010; + +#if defined(LCD_800x480) + #if defined(LCD_PORTRAIT) + const int16_t font_small = 29; + const int16_t font_medium = 30; + const int16_t font_large = 30; + #else + const int16_t font_small = 30; + const int16_t font_medium = 30; + const int16_t font_large = 31; + #endif + const float icon_scale = 1.0; +#else + #if defined(LCD_PORTRAIT) + const int16_t font_small = 27; + const int16_t font_medium = 28; + const int16_t font_large = 28; + #else + const int16_t font_small = 28; + const int16_t font_medium = 29; + const int16_t font_large = 30; + #endif + const float icon_scale = 0.7; +#endif +}; + +/******************************** BOOT SCREEN ****************************/ + +void BootScreen::onRefresh() { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Clear(1,1,1); + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); + + cmd.Wait_Until_Idle(); + + CLCD::Turn_On_Backlight(); +} + +void BootScreen::onIdle() { + GOTO_SCREEN(CalibrationScreen); +} + +/******************************** ABOUT SCREEN ****************************/ + + +void AboutScreen::onEntry() { + draw(false); + playChime(); + draw(true); +} + +void AboutScreen::onRefresh() { + draw(true); +} + +void AboutScreen::draw(bool showOkay) { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + cmd.Cmd_Clear_Color(Theme::about_bg); + cmd.Cmd_Clear(1,1,1); + + #define GRID_COLS 4 + #define GRID_ROWS 6 + + BTX( BTN_POS(1,2), BTN_SIZE(4,1), F("Color LCD Interface"), FONT_LRG); + BTN_TAG(2) BTX( BTN_POS(1,3), BTN_SIZE(4,1), F("(c) 2018 Aleph Objects, Inc."), FONT_LRG); + + if(showOkay) { + BTN_TAG(1) RGB(about_btn) BTN( BTN_POS(2,5), BTN_SIZE(2,1), F("Okay"), MENU_BTN_STYLE); + } + + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); +} + +void AboutScreen::onTouchStart(uint8_t tag) { + switch(tag) { + case 1: GOTO_PREVIOUS(); return; + case 2: GOTO_SCREEN(CalibrationRegistersScreen); return; + } +} + +void AboutScreen::playChime() { + CLCD::Mem_Write8(REG_VOL_SOUND, 0xFF); + CLCD::Mem_Write16(REG_SOUND, (0x37<< 8) | 0x47); // C8 MIDI note on xylophone 37 + CLCD::Mem_Write8(REG_PLAY, 1); + + delay(800); + + CLCD::Mem_Write16(REG_SOUND, (0x40<< 8) | 0x47); // C8 MIDI note on xylophone 40 + CLCD::Mem_Write8(REG_PLAY, 1); + + delay(800); + + CLCD::Mem_Write16(REG_SOUND, (0x3C<< 8) | 0x47); // C8 MIDI note on xylophone 3C + CLCD::Mem_Write8(REG_PLAY, 1); + + delay(1200); + + CLCD::Mem_Write16(REG_SOUND, 0); + CLCD::Mem_Write8(REG_PLAY, 1); +} + +/*********************************** STATUS SCREEN ******************************/ + +void StatusScreen::onStartup() { + // Load USB Thumb Drive Bitmap + CLCD::Flash_Write_RGB332_Bitmap(TD_Icon_Info.RAMG_addr, TD_Icon, sizeof(TD_Icon)); + + // Load Extruder Bitmap + CLCD::Flash_Write_RGB332_Bitmap(Extruder_Icon_Info.RAMG_addr, Extruder_Icon, sizeof(Extruder_Icon)); + + // Load Bed Heat Bitmap + CLCD::Flash_Write_RGB332_Bitmap(Bed_Heat_Icon_Info.RAMG_addr, Bed_Heat_Icon, sizeof(Bed_Heat_Icon)); + + // Load Fan Percent Bitmap + CLCD::Flash_Write_RGB332_Bitmap(Fan_Icon_Info.RAMG_addr, Fan_Icon, sizeof(Fan_Icon)); +} + +void StatusScreen::onRefresh() { + static CLCD::DLCache dlcache; + + if(dlcache.hasData()) { + dlcache.append(); + } else { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Clear(1,1,1); + + #if defined(LCD_PORTRAIT) + #define GRID_ROWS 9 + #else + #define GRID_ROWS 8 + #endif + + BTN_TAG(0) + #if defined(LCD_PORTRAIT) + #define GRID_COLS 8 + RGB(temp) BTN( BTN_POS(1,1), BTN_SIZE(4,2), F(""), FONT_SML, OPT_FLAT); + RGB(temp) BTN( BTN_POS(1,1), BTN_SIZE(8,1), F(""), FONT_SML, OPT_FLAT); + RGB(fan_speed) BTN( BTN_POS(5,2), BTN_SIZE(4,1), F(""), FONT_SML, OPT_FLAT); + RGB(progress) BTN( BTN_POS(1,3), BTN_SIZE(4,1), F(""), FONT_SML, OPT_FLAT); + RGB(progress) BTN( BTN_POS(5,3), BTN_SIZE(4,1), F(""), FONT_SML, OPT_FLAT); + #else + #define GRID_COLS 12 + RGB(temp) BTN( BTN_POS(1,1), BTN_SIZE(4,2), F(""), FONT_SML, OPT_FLAT); + RGB(temp) BTN( BTN_POS(1,1), BTN_SIZE(8,1), F(""), FONT_SML, OPT_FLAT); + RGB(fan_speed) BTN( BTN_POS(5,2), BTN_SIZE(4,1), F(""), FONT_SML, OPT_FLAT); + RGB(progress) BTN( BTN_POS(9,1), BTN_SIZE(4,1), F(""), FONT_SML, OPT_FLAT); + RGB(progress) BTN( BTN_POS(9,2), BTN_SIZE(4,1), F(""), FONT_SML, OPT_FLAT); + #endif + + #if defined(LCD_PORTRAIT) + #define GRID_COLS 3 + RGB(axis_label) BTN( BTN_POS(1,5), BTN_SIZE(2,1), F(""), FONT_LRG, OPT_FLAT); + RGB(axis_label) BTN( BTN_POS(1,6), BTN_SIZE(2,1), F(""), FONT_LRG, OPT_FLAT); + RGB(axis_label) BTN( BTN_POS(1,7), BTN_SIZE(2,1), F(""), FONT_LRG, OPT_FLAT); + BTX( BTN_POS(1,5), BTN_SIZE(1,1), F("X"), FONT_SML); + BTX( BTN_POS(1,6), BTN_SIZE(1,1), F("Y"), FONT_SML); + BTX( BTN_POS(1,7), BTN_SIZE(1,1), F("Z"), FONT_SML); + RGB(x_axis) BTN( BTN_POS(2,5), BTN_SIZE(2,1), F(""), FONT_MED, OPT_FLAT); + RGB(y_axis) BTN( BTN_POS(2,6), BTN_SIZE(2,1), F(""), FONT_MED, OPT_FLAT); + RGB(z_axis) BTN( BTN_POS(2,7), BTN_SIZE(2,1), F(""), FONT_MED, OPT_FLAT); + #else + #define GRID_COLS 3 + #define MARGIN_T 10 + RGB(axis_label) BTN( BTN_POS(1,5), BTN_SIZE(1,2), F(""), FONT_LRG, OPT_FLAT); + RGB(axis_label) BTN( BTN_POS(2,5), BTN_SIZE(1,2), F(""), FONT_LRG, OPT_FLAT); + RGB(axis_label) BTN( BTN_POS(3,5), BTN_SIZE(1,2), F(""), FONT_LRG, OPT_FLAT); + BTX( BTN_POS(1,5), BTN_SIZE(1,1), F("X"), FONT_SML); + BTX( BTN_POS(2,5), BTN_SIZE(1,1), F("Y"), FONT_SML); + BTX( BTN_POS(3,5), BTN_SIZE(1,1), F("Z"), FONT_SML); + #define MARGIN_T 0 + RGB(x_axis) BTN( BTN_POS(1,6), BTN_SIZE(1,1), F(""), FONT_MED, OPT_FLAT); + RGB(y_axis) BTN( BTN_POS(2,6), BTN_SIZE(1,1), F(""), FONT_MED, OPT_FLAT); + RGB(z_axis) BTN( BTN_POS(3,6), BTN_SIZE(1,1), F(""), FONT_MED, OPT_FLAT); + #define MARGIN_T 5 + #endif + + #define GRID_COLS 4 + #if defined(LCD_PORTRAIT) + BTN_TAG(1) RGB(stop_btn) BTN( BTN_POS(1,8), BTN_SIZE(4,1), F("STOP"), MENU_BTN_STYLE); + BTN_TAG(3) RGB(navi_btn) BTN( BTN_POS(1,9), BTN_SIZE(2,1), F(""), MENU_BTN_STYLE); + BTN_TAG(4) RGB(navi_btn) BTN( BTN_POS(3,9), BTN_SIZE(2,1), F("MENU"), MENU_BTN_STYLE); + #else + BTN_TAG(1) RGB(stop_btn) BTN( BTN_POS(1,7), BTN_SIZE(2,2), F("STOP"), MENU_BTN_STYLE); + BTN_TAG(3) RGB(navi_btn) BTN( BTN_POS(3,7), BTN_SIZE(1,2), F(""), MENU_BTN_STYLE); + BTN_TAG(4) RGB(navi_btn) BTN( BTN_POS(4,7), BTN_SIZE(1,2), F("MENU"), MENU_BTN_STYLE); + #endif + + // Draw Thumb Drive Bitmap on USB Button + + cmd.Cmd_Bitmap_Source(TD_Icon_Info); + cmd.Cmd_Bitmap_Layout(TD_Icon_Info); + cmd.Cmd_Bitmap_Size (TD_Icon_Info); + + BTN_TAG(3) + #if defined(LCD_PORTRAIT) + BTI(BTN_POS(1,9), BTN_SIZE(2,1), TD_Icon_Info, Theme::icon_scale); + #else + BTI(BTN_POS(3,7), BTN_SIZE(1,2), TD_Icon_Info, Theme::icon_scale); + #endif + + #if defined(LCD_PORTRAIT) + #define GRID_COLS 8 + #else + #define GRID_COLS 12 + #endif + + // Draw Extruder Bitmap on Extruder Temperature Button + + cmd.Cmd_Bitmap_Source(Extruder_Icon_Info); + cmd.Cmd_Bitmap_Layout(Extruder_Icon_Info); + cmd.Cmd_Bitmap_Size (Extruder_Icon_Info); + + BTN_TAG(0) + BTI(BTN_POS(1,1), BTN_SIZE(1,1), Extruder_Icon_Info, Theme::icon_scale); + BTI(BTN_POS(5,1), BTN_SIZE(1,1), Extruder_Icon_Info, Theme::icon_scale); + + #if EXTRUDERS == 1 + BTX( BTN_POS(6,1), BTN_SIZE(2,1), F("-"), FONT_MED); + #endif + + // Draw Bed Heat Bitmap on Bed Heat Button + cmd.Cmd_Bitmap_Source(Bed_Heat_Icon_Info); + cmd.Cmd_Bitmap_Layout(Bed_Heat_Icon_Info); + cmd.Cmd_Bitmap_Size (Bed_Heat_Icon_Info); + + BTN_TAG(0) + BTI(BTN_POS(1,2), BTN_SIZE(1,1), Bed_Heat_Icon_Info, Theme::icon_scale); + + // Draw Fan Percent Bitmap on Bed Heat Button + + cmd.Cmd_Bitmap_Source(Fan_Icon_Info); + cmd.Cmd_Bitmap_Layout(Fan_Icon_Info); + cmd.Cmd_Bitmap_Size (Fan_Icon_Info); + + BTN_TAG(0) + BTI(BTN_POS(5,2), BTN_SIZE(1,1), Fan_Icon_Info, Theme::icon_scale); + + cmd.Cmd_Execute(); + dlcache.store(); + } + + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + /* Dynamic content, non-cached data follows */ + + #if defined(LCD_PORTRAIT) + #define GRID_ROWS 9 + #else + #define GRID_ROWS 8 + #endif + + BTN_TAG(0) + + const uint32_t elapsed = Marlin_LCD_API::getProgress_seconds_elapsed(); + const uint8_t hrs = elapsed/3600; + const uint8_t min = (elapsed/60)%60; + char b[255]; + #if defined(LCD_PORTRAIT) + #define GRID_COLS 8 + sprintf_P(b, PSTR(" %02d : %02d"), hrs, min); + BTX( BTN_POS(1,3), BTN_SIZE(4,1), b, FONT_MED); + + sprintf_P(b, PSTR("%-3d %%"), Marlin_LCD_API::getProgress_percent() ); + BTX( BTN_POS(5,3), BTN_SIZE(4,1), b, FONT_MED); + #else + #define GRID_COLS 12 + sprintf_P(b, PSTR(" %02d : %02d"), hrs, min); + BTX( BTN_POS(9,1), BTN_SIZE(4,1), b, FONT_MED); + + sprintf_P(b, PSTR("%-3d %%"), Marlin_LCD_API::getProgress_percent() ); + BTX( BTN_POS(9,2), BTN_SIZE(4,1), b, FONT_MED); + #endif + + sprintf_P(b, PSTR("%-3d / %-3d C"), Marlin_LCD_API::getActualTemp_celsius(1), Marlin_LCD_API::getActualTemp_celsius(1) ); + BTX( BTN_POS(2,1), BTN_SIZE(3,1), b, FONT_MED); + + #if EXTRUDERS == 2 + sprintf_P(b, PSTR("%-3d / %-3d C"), Marlin_LCD_API::getActualTemp_celsius(2), Marlin_LCD_API::getTargetTemp_celsius(2) ); + BTX( BTN_POS(6,1), BTN_SIZE(3,1), b, FONT_MED); + #endif + + sprintf_P(b, PSTR("%-3d / %-3d " ), Marlin_LCD_API::getActualTemp_celsius(0), Marlin_LCD_API::getActualTemp_celsius(0) ); + BTX( BTN_POS(2,2), BTN_SIZE(3,1), b, FONT_MED); + + sprintf_P(b, PSTR("%-3d %%"), Marlin_LCD_API::getFan_percent(0) ); + BTX( BTN_POS(6,2), BTN_SIZE(3,1), b, FONT_MED); + + #define GRID_COLS 1 + #if defined(LCD_PORTRAIT) + RGB(status_msg) BTN( BTN_POS(1,4), BTN_SIZE(1,1), lcd_status_message, FONT_LRG, OPT_FLAT); + #else + RGB(status_msg) BTN( BTN_POS(1,3), BTN_SIZE(1,2), lcd_status_message, FONT_LRG, OPT_FLAT); + #endif + + #define GRID_COLS 3 + + dtostrf(Marlin_LCD_API::getAxisPosition_mm(Marlin_LCD_API::X), 5, 1, b); + strcat_P(b, PSTR(" mm")); + #if defined(LCD_PORTRAIT) + BTX( BTN_POS(2,5), BTN_SIZE(2,1), b, FONT_MED); + #else + BTX( BTN_POS(1,6), BTN_SIZE(1,1), b, FONT_MED); + #endif + + + dtostrf(Marlin_LCD_API::getAxisPosition_mm(Marlin_LCD_API::Y), 5, 1, b); + strcat_P(b, PSTR(" mm")); + #if defined(LCD_PORTRAIT) + BTX( BTN_POS(2,6), BTN_SIZE(2,1), b, FONT_MED); + #else + BTX( BTN_POS(2,6), BTN_SIZE(1,1), b, FONT_MED); + #endif + + dtostrf(Marlin_LCD_API::getAxisPosition_mm(Marlin_LCD_API::Z), 5, 1, b); + strcat_P(b, PSTR(" mm")); + #if defined(LCD_PORTRAIT) + BTX( BTN_POS(2,7), BTN_SIZE(2,1), b, FONT_MED); + #else + BTX( BTN_POS(3,6), BTN_SIZE(1,1), b, FONT_MED); + #endif + + #define MARGIN_T 5 + + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); +} + +void StatusScreen::onEntry() { + onRefresh(); +} + +void StatusScreen::onIdle() { + onRefresh(); +} + +void StatusScreen::onTouchStart(uint8_t tag) { + switch(tag) { + case 4: GOTO_SCREEN(MenuScreen); break; + } +} + +/************************************ MENU SCREEN *******************************/ + +void MenuScreen::onRefresh() { + static CLCD::DLCache dlcache; + + if(dlcache.hasData()) { + dlcache.append(); + } else { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + + cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Clear(1,1,1); + + #if defined(LCD_PORTRAIT) + #define GRID_ROWS 7 + #define GRID_COLS 2 + BTN_TAG(2) RGB(menu_btn) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Auto Home"), MENU_BTN_STYLE); + BTN_TAG(3) RGB(menu_btn) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Move Axis"), MENU_BTN_STYLE); + + #define GRID_COLS 1 + BTN_TAG(4) RGB(menu_btn) BTN( BTN_POS(1,2), BTN_SIZE(1,1), F("Disable Steppers"), MENU_BTN_STYLE); + + BTN_TAG(5) RGB(menu_btn) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("Temperature"), MENU_BTN_STYLE); + BTN_TAG(6) RGB(menu_btn) BTN( BTN_POS(1,4), BTN_SIZE(1,1), F("Advanced Settings"), MENU_BTN_STYLE); + BTN_TAG(8) RGB(menu_btn) BTN( BTN_POS(1,5), BTN_SIZE(1,1), F("Recalibrate Screen"), MENU_BTN_STYLE); + BTN_TAG(7) RGB(menu_btn) BTN( BTN_POS(1,6), BTN_SIZE(1,1), F("About Firmware"), MENU_BTN_STYLE); + + #define MARGIN_T 15 + BTN_TAG(1) RGB(navi_btn) BTN( BTN_POS(1,7), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); + #define MARGIN_T 5 + #else + #define GRID_ROWS 4 + #define GRID_COLS 2 + BTN_TAG(2) RGB(menu_btn) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Auto Home"), MENU_BTN_STYLE); + BTN_TAG(3) RGB(menu_btn) BTN( BTN_POS(1,2), BTN_SIZE(1,1), F("Move Axis"), MENU_BTN_STYLE); + BTN_TAG(4) RGB(menu_btn) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("Disable Steppers"), MENU_BTN_STYLE); + + BTN_TAG(5) RGB(menu_btn) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Temperature"), MENU_BTN_STYLE); + BTN_TAG(6) RGB(menu_btn) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Configuration"), MENU_BTN_STYLE); + BTN_TAG(7) RGB(menu_btn) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("About Firmware"), MENU_BTN_STYLE); + + #define MARGIN_T 15 + #define GRID_COLS 1 + BTN_TAG(1) RGB(navi_btn) BTN( BTN_POS(1,4), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); + #define MARGIN_T 5 + #endif + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); + dlcache.store(); + } +} + +void MenuScreen::onTouchStart(uint8_t tag) { + switch(tag) { + case 1: GOTO_PREVIOUS(); break; + case 3: GOTO_SCREEN(MoveAxisScreen); break; + case 5: GOTO_SCREEN(TemperatureScreen); break; + case 6: GOTO_SCREEN(AdvancedSettingsScreen); break; + case 7: GOTO_SCREEN(AboutScreen); break; + case 8: GOTO_SCREEN(CalibrationScreen); break; + } +} + +/******************************* CONFIGURATION SCREEN ****************************/ + +void AdvancedSettingsScreen::onRefresh() { + static CLCD::DLCache dlcache; + + if(dlcache.hasData()) { + dlcache.append(); + } else { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + + cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Clear(1,1,1); + + #if defined(LCD_PORTRAIT) + #define GRID_ROWS 6 + #else + #define GRID_ROWS 4 + #endif + + #define GRID_COLS 2 + + #define MARGIN_T 15 + #if defined(LCD_PORTRAIT) + BTN_TAG(3) RGB(menu_btn) BTN( BTN_POS(1,1), BTN_SIZE(1,2), F("Z Offset "), MENU_BTN_STYLE); + BTN_TAG(4) RGB(menu_btn) BTN( BTN_POS(1,3), BTN_SIZE(1,2), F("Steps/mm"), MENU_BTN_STYLE); + + BTN_TAG(6) RGB(disabled) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Velocity "), MENU_BTN_STYLE); + BTN_TAG(7) RGB(disabled) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Acceleration"), MENU_BTN_STYLE); + BTN_TAG(8) RGB(disabled) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("Jerk"), MENU_BTN_STYLE); + BTN_TAG(5) RGB(menu_btn) BTN( BTN_POS(1,5), BTN_SIZE(2,1), F("Restore Failsafe"), MENU_BTN_STYLE); + BTN_TAG(1) RGB(navi_btn) BTN( BTN_POS(1,6), BTN_SIZE(1,1), F("Save"), MENU_BTN_STYLE); + BTN_TAG(2) RGB(navi_btn) BTN( BTN_POS(2,6), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); + #else + BTN_TAG(3) RGB(menu_btn) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("Z Offset "), MENU_BTN_STYLE); + BTN_TAG(4) RGB(menu_btn) BTN( BTN_POS(1,2), BTN_SIZE(1,1), F("Steps/mm"), MENU_BTN_STYLE); + + BTN_TAG(6) RGB(disabled) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F("Velocity "), MENU_BTN_STYLE); + BTN_TAG(7) RGB(disabled) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F("Acceleration"), MENU_BTN_STYLE); + BTN_TAG(8) RGB(disabled) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F("Jerk"), MENU_BTN_STYLE); + BTN_TAG(5) RGB(menu_btn) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("Restore Failsafe"), MENU_BTN_STYLE); + #define GRID_COLS 4 + BTN_TAG(1) RGB(navi_btn) BTN( BTN_POS(1,4), BTN_SIZE(2,1), F("Save"), MENU_BTN_STYLE); + BTN_TAG(2) RGB(navi_btn) BTN( BTN_POS(3,4), BTN_SIZE(2,1), F("Back"), MENU_BTN_STYLE); + #endif + + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + + cmd.Cmd_Execute(); + dlcache.store(); + } +} + +void AdvancedSettingsScreen::onTouchStart(uint8_t tag) { + switch(tag) { + case 1: GOTO_PREVIOUS(); break; + case 2: GOTO_PREVIOUS(); break; + case 3: GOTO_SCREEN(ZOffsetScreen); break; + case 4: GOTO_SCREEN(StepsScreen); break; + } +} + +/******************************** CALIBRATION SCREEN ****************************/ + +void CalibrationScreen::onRefresh() { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Clear(1,1,1); + + #define GRID_COLS 4 + #define GRID_ROWS 16 + #if defined(LCD_PORTRAIT) + BTX( BTN_POS(1,8), BTN_SIZE(4,1), F("Touch the dots"), FONT_LRG); + BTX( BTN_POS(1,9), BTN_SIZE(4,1), F("to calibrate"), FONT_LRG); + #else + BTX( BTN_POS(1,1), BTN_SIZE(4,16), F("Touch the dots to calibrate"), FONT_LRG); + #endif + + cmd.Cmd(CMD_CALIBRATE); + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); +} + +void CalibrationScreen::onIdle() { + if(CLCD::CommandFifo::Is_Idle()) { + GOTO_SCREEN(StatusScreen); + } +} + +/***************************** CALIBRATION REGISTERS SCREEN ****************************/ + +void CalibrationRegistersScreen::onRefresh() { + const uint32_t T_Transform_A = CLCD::Mem_Read32(REG_TOUCH_TRANSFORM_A); + const uint32_t T_Transform_B = CLCD::Mem_Read32(REG_TOUCH_TRANSFORM_B); + const uint32_t T_Transform_C = CLCD::Mem_Read32(REG_TOUCH_TRANSFORM_C); + const uint32_t T_Transform_D = CLCD::Mem_Read32(REG_TOUCH_TRANSFORM_D); + const uint32_t T_Transform_E = CLCD::Mem_Read32(REG_TOUCH_TRANSFORM_E); + const uint32_t T_Transform_F = CLCD::Mem_Read32(REG_TOUCH_TRANSFORM_F); + char b[20]; + + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + cmd.Cmd_Clear_Color(Theme::background); + cmd.Cmd_Clear(1,1,1); + + #define MARGIN_T 5 + #define GRID_ROWS 7 + #define GRID_COLS 2 + BTN_TAG(0) + RGB(transformA) BTN( BTN_POS(1,1), BTN_SIZE(1,1), F("TOUCH TRANSFORM_A"), 28, OPT_3D); + RGB(transformB) BTN( BTN_POS(1,2), BTN_SIZE(1,1), F("TOUCH TRANSFORM_B"), 28, OPT_3D); + RGB(transformC) BTN( BTN_POS(1,3), BTN_SIZE(1,1), F("TOUCH TRANSFORM_C"), 28, OPT_3D); + RGB(transformD) BTN( BTN_POS(1,4), BTN_SIZE(1,1), F("TOUCH TRANSFORM_D"), 28, OPT_3D); + RGB(transformE) BTN( BTN_POS(1,5), BTN_SIZE(1,1), F("TOUCH TRANSFORM_E"), 28, OPT_3D); + RGB(transformF) BTN( BTN_POS(1,6), BTN_SIZE(1,1), F("TOUCH TRANSFORM_F"), 28, OPT_3D); + + RGB(transformVal) BTN( BTN_POS(2,1), BTN_SIZE(1,1), F(""), 28, OPT_FLAT); + RGB(transformVal) BTN( BTN_POS(2,2), BTN_SIZE(1,1), F(""), 28, OPT_FLAT); + RGB(transformVal) BTN( BTN_POS(2,3), BTN_SIZE(1,1), F(""), 28, OPT_FLAT); + RGB(transformVal) BTN( BTN_POS(2,4), BTN_SIZE(1,1), F(""), 28, OPT_FLAT); + RGB(transformVal) BTN( BTN_POS(2,5), BTN_SIZE(1,1), F(""), 28, OPT_FLAT); + RGB(transformVal) BTN( BTN_POS(2,6), BTN_SIZE(1,1), F(""), 28, OPT_FLAT); + + sprintf(b, "0x%08lX", T_Transform_A); BTX( BTN_POS(2,1), BTN_SIZE(1,1), b, 28); + sprintf(b, "0x%08lX", T_Transform_B); BTX( BTN_POS(2,2), BTN_SIZE(1,1), b, 28); + sprintf(b, "0x%08lX", T_Transform_C); BTX( BTN_POS(2,3), BTN_SIZE(1,1), b, 28); + sprintf(b, "0x%08lX", T_Transform_D); BTX( BTN_POS(2,4), BTN_SIZE(1,1), b, 28); + sprintf(b, "0x%08lX", T_Transform_E); BTX( BTN_POS(2,5), BTN_SIZE(1,1), b, 28); + sprintf(b, "0x%08lX", T_Transform_F); BTX( BTN_POS(2,6), BTN_SIZE(1,1), b, 28); + + #define GRID_COLS 3 + + BTN_TAG(1) RGB(navi_btn) BTN( BTN_POS(3,7), BTN_SIZE(1,1), F("Back"), MENU_BTN_STYLE); + + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); +} + +void CalibrationRegistersScreen::onTouchStart(uint8_t tag) { + switch(tag) { + case 1: GOTO_PREVIOUS(); return; + } +} + +/*************************** GENERIC VALUE ADJUSTMENT SCREEN ******************************/ + +void ValueAdjusters::static_heading(progmem_str heading) { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd_Clear_Color(Theme::adjust_bg); + cmd.Cmd_Clear(1,1,1); + + #if defined(LCD_PORTRAIT) + #define GRID_COLS 6 + #define GRID_ROWS 9 + #define EDGE_R 20 + #else + #define GRID_COLS 9 + #define GRID_ROWS 6 + #define EDGE_R 40 + #endif + + #if defined(LCD_PORTRAIT) + BTN_TAG( 0) RGB(adjust_bg) BTN( BTN_POS(1,1), BTN_SIZE(6,1), heading, FONT_MED, OPT_FLAT); + BTN_TAG( 0) RGB(adjust_bg) BTN( BTN_POS(1,7), BTN_SIZE(2,1), F("Increment:"), FONT_SML, OPT_FLAT); + + BTN_TAG(20) TOGGLE(increment == 0.1 ) BTN( BTN_POS(3,7), BTN_SIZE(1,1), F("0.1"), FONT_MED, OPT_3D); + BTN_TAG(21) TOGGLE(increment == 1. ) BTN( BTN_POS(4,7), BTN_SIZE(1,1), F("1"), FONT_MED, OPT_3D); + BTN_TAG(22) TOGGLE(increment == 10. ) BTN( BTN_POS(5,7), BTN_SIZE(1,1), F("10"), FONT_MED, OPT_3D); + BTN_TAG(23) TOGGLE(increment == 100.) BTN( BTN_POS(6,7), BTN_SIZE(1,1), F("100"), FONT_MED, OPT_3D); + + #define EDGE_R 0 + #define GRID_COLS 4 + BTN_TAG(1) RGB(navi_btn) BTN( BTN_POS(1,9), BTN_SIZE(4,1), F("Back"), MENU_BTN_STYLE); + #else + BTN_TAG( 0) RGB(adjust_bg) BTN( BTN_POS(3,1), BTN_SIZE(4,1), heading, FONT_MED, OPT_FLAT); + + BTN_TAG( 0) RGB(adjust_bg) BTN( BTN_POS(8,1), BTN_SIZE(2,1), F("Increment"), FONT_MED, OPT_FLAT); + + BTN_TAG(20) TOGGLE(increment == 0.1 ) BTN( BTN_POS(8,2), BTN_SIZE(1,1), F("0.1"), FONT_MED, OPT_3D); + BTN_TAG(21) TOGGLE(increment == 1. ) BTN( BTN_POS(9,2), BTN_SIZE(1,1), F("1"), FONT_MED, OPT_3D); + BTN_TAG(22) TOGGLE(increment == 10. ) BTN( BTN_POS(8,3), BTN_SIZE(2,1), F("10"), FONT_MED, OPT_3D); + BTN_TAG(23) TOGGLE(increment == 100.) BTN( BTN_POS(8,4), BTN_SIZE(2,1), F("100"), FONT_MED, OPT_3D); + + #define EDGE_R 0 + + #define MARGIN_T 15 + #define GRID_COLS 4 + BTN_TAG(1) RGB(navi_btn) BTN( BTN_POS(1,6), BTN_SIZE(4,1), F("Back"), MENU_BTN_STYLE); + #define MARGIN_T 5 + #endif + + cmd.Cmd_Execute(); +} + +void ValueAdjusters::static_value(int line, progmem_str label) { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + + #if defined(LCD_PORTRAIT) + #define GRID_COLS 6 + #define GRID_ROWS 9 + #define EDGE_R 20 + #else + #define GRID_COLS 9 + #define GRID_ROWS 6 + #define EDGE_R 40 + #endif + + BTN_TAG( 0) BTN( BTN_POS(3,line+1), BTN_SIZE(2,1), F(""), FONT_SML, OPT_FLAT); + BTN_TAG( 0) RGB(adjust_bg) BTN( BTN_POS(1,line+1), BTN_SIZE(2,1), label, FONT_SML, OPT_FLAT); + BTN_TAG(2*line ) RGB(incr_btn) BTN( BTN_POS(5,line+1), BTN_SIZE(1,1), F("-"), FONT_MED, OPT_3D); + BTN_TAG(2*line + 1) RGB(incr_btn) BTN( BTN_POS(6,line+1), BTN_SIZE(1,1), F("+"), FONT_MED, OPT_3D); + + #define EDGE_R 0 + + cmd.Cmd_Execute(); +} + +void ValueAdjusters::dynamic_value(int line, float value, progmem_str units) { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + #define MARGIN_T 5 + + #if defined(LCD_PORTRAIT) + #define GRID_COLS 6 + #define GRID_ROWS 9 + #define EDGE_R 20 + #else + #define GRID_COLS 9 + #define GRID_ROWS 6 + #define EDGE_R 40 + #endif + + BTN_TAG( 0) + + char b[255]; + dtostrf(value, 5, 1, b); + strcat_P(b, PSTR(" ")); + strcat_P(b, (const char*) units); + BTX( BTN_POS(3,line+1), BTN_SIZE(2,1), b, FONT_SML); + + #define EDGE_R 0 + + cmd.Cmd_Execute(); +} + +void ValueAdjusters::onTouchStart(uint8_t tag) { + switch(tag) { + case 1: GOTO_PREVIOUS(); return; + case 2 ... 9: current_screen.onTouchHeld(tag); return; + case 20: increment = 0.1; break; + case 21: increment = 1; break; + case 22: increment = 10; break; + case 23: increment = 100; break; + } + current_screen.onRefresh(); +} + +float ValueAdjusters::increment = 1; + +/******************************** MOVE AXIS SCREEN ******************************/ + +void MoveAxisScreen::onRefresh() { + static CLCD::DLCache dlcache; + + if(dlcache.hasData()) { + dlcache.append(); + } else { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + cmd.Cmd_Execute(); + + ValueAdjusters::static_heading(F("Move Axis")); + RGB(x_axis) ValueAdjusters::static_value(1, F("X:")); + RGB(y_axis) ValueAdjusters::static_value(2, F("Y:")); + RGB(z_axis) ValueAdjusters::static_value(3, F("Z:")); + dlcache.store(); + } + + ValueAdjusters::dynamic_value(1, marlin_x_axis, F("mm")); + ValueAdjusters::dynamic_value(2, marlin_y_axis, F("mm")); + ValueAdjusters::dynamic_value(3, marlin_z_axis, F("mm")); + + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); +} + +void MoveAxisScreen::onTouchHeld(uint8_t tag) { + switch(tag) { + case 2: marlin_x_axis -= increment; break; + case 3: marlin_x_axis += increment; break; + case 4: marlin_y_axis -= increment; break; + case 5: marlin_y_axis += increment; break; + case 6: marlin_z_axis -= increment; break; + case 7: marlin_z_axis += increment; break; + } + onRefresh(); +} + +/******************************* TEMPERATURE SCREEN ******************************/ + +void TemperatureScreen::onRefresh() { + static CLCD::DLCache dlcache; + + if(dlcache.hasData()) { + dlcache.append(); + } else { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + + ValueAdjusters::static_heading(F("Temperature")); + RGB(x_axis) ValueAdjusters::static_value(1, F("Nozzle:")); + RGB(y_axis) ValueAdjusters::static_value(2, F("Bed:")); + RGB(z_axis) ValueAdjusters::static_value(3, F("Fan Speed:")); + + cmd.Cmd_Execute(); + dlcache.store(); + } + + ValueAdjusters::dynamic_value(1, marlin_e0_temp, F("C")); + ValueAdjusters::dynamic_value(2, marlin_bed_temp, F("C")); + ValueAdjusters::dynamic_value(3, marlin_fan_speed, F("%")); + + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); +} + +void TemperatureScreen::onTouchHeld(uint8_t tag) { + switch(tag) { + case 2: marlin_e0_temp -= increment; break; + case 3: marlin_e0_temp += increment; break; + case 4: marlin_bed_temp -= increment; break; + case 5: marlin_bed_temp += increment; break; + case 6: marlin_fan_speed -= increment; break; + case 7: marlin_fan_speed += increment; break; + } + onRefresh(); +} + +/******************************* STEPS SCREEN ******************************/ + +void StepsScreen::onRefresh() { + static CLCD::DLCache dlcache; + + if(dlcache.hasData()) { + dlcache.append(); + } else { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + + ValueAdjusters::static_heading(F("Steps/mm")); + RGB(x_axis) ValueAdjusters::static_value(1, F("X:")); + RGB(y_axis) ValueAdjusters::static_value(2, F("Y:")); + RGB(z_axis) ValueAdjusters::static_value(3, F("Z:")); + RGB(e_axis) ValueAdjusters::static_value(4, F("E:")); + + cmd.Cmd_Execute(); + dlcache.store(); + } + + ValueAdjusters::dynamic_value(1, marlin_x_steps, F("")); + ValueAdjusters::dynamic_value(2, marlin_y_steps, F("")); + ValueAdjusters::dynamic_value(3, marlin_z_steps, F("")); + ValueAdjusters::dynamic_value(4, marlin_e0_steps, F("")); + + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); +} + +void StepsScreen::onTouchHeld(uint8_t tag) { + switch(tag) { + case 2: marlin_x_steps -= increment; break; + case 3: marlin_x_steps += increment; break; + case 4: marlin_y_steps -= increment; break; + case 5: marlin_y_steps += increment; break; + case 6: marlin_z_steps -= increment; break; + case 7: marlin_z_steps += increment; break; + case 8: marlin_e0_steps -= increment; break; + case 9: marlin_e0_steps += increment; break; + } + onRefresh(); +} + +/***************************** Z-OFFSET SCREEN ***************************/ + +void ZOffsetScreen::onRefresh() { + static CLCD::DLCache dlcache; + + if(dlcache.hasData()) { + dlcache.append(); + } else { + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(CMD_DLSTART); + + ValueAdjusters::static_heading(F("Z Offset")); + RGB(z_axis) ValueAdjusters::static_value(2, F("Z Offset:")); + + cmd.Cmd_Execute(); + dlcache.store(); + } + + ValueAdjusters::dynamic_value(2, marlin_z_offset, F("mm")); + + CLCD::CommandFifo cmd; + cmd.Cmd_Start(); + cmd.Cmd(DL_DISPLAY); + cmd.Cmd(CMD_SWAP); + cmd.Cmd_Execute(); +} + +void ZOffsetScreen::onTouchHeld(uint8_t tag) { + switch(tag) { + case 4: marlin_z_offset -= increment; break; + case 5: marlin_z_offset += increment; break; + } + onRefresh(); +} + +/******************************** MAIN EVENT HANDLER *******************************/ + +#define DISPLAY_UPDATE_INTERVAL 1000 + +void lcd_init() { + CLCD::Init(); + current_screen.start(); +} + +void lcd_update() { + const uint8_t NONE = 0xFF; + const uint8_t IGNORE = 0xFE; + static uint8_t pressed = NONE; + static uint32_t last_repeat = 0; + static uint32_t last_update = 0; + + if(millis() - last_update > DISPLAY_UPDATE_INTERVAL) { + current_screen.onIdle(); + last_update = millis(); + } + + // If the LCD is processing commands, don't check + // for tags since they may be changing and could + // cause spurious events. + if(!CLCD::CommandFifo::Is_Idle()) { + return; + } + + CLCD::Test_Pulse(); + + const uint8_t tag = CLCD::Get_Tag(); + + if(tag == 0) { + // When the user lifts their finger, activate the onTouchEnd handler, + // except when pressed is IGNORE. + if(pressed == IGNORE) { + pressed = NONE; + } + else if(pressed != NONE) { + current_screen.onTouchEnd(pressed); + pressed = NONE; + } + } + else if(pressed == NONE) { + // When the user taps on a button, activate the onTouchStart handler + const uint8_t lastScreen = current_screen.getScreen(); + current_screen.onTouchStart(tag); + last_repeat = millis(); + + #if defined(UI_FRAMEWORK_DEBUG) + Serial.print("Touch start: "); + Serial.println(tag); + #endif + + if(lastScreen != current_screen.getScreen()) { + // In the case in which a touch event triggered a new screen to be + // drawn, we don't issue a touchEnd since it would be sent to the + // wrong screen. + pressed = IGNORE; + } else { + pressed = tag; + } + } else if(tag == pressed) { + // The user is holding down a button. + if((millis() - last_repeat) > 250) { + current_screen.onTouchHeld(tag); + last_repeat = millis(); + } + } +} + +inline bool lcd_hasstatus() { return true; } + +void lcd_setstatus(const char * const message, const bool persist = false) { + strncpy(lcd_status_message, message, STATUS_MESSAGE_BUFFER_LENGTH); +} + +void lcd_setstatusPGM(const char * const message, int8_t level = 0) { + strncpy_P(lcd_status_message, message, STATUS_MESSAGE_BUFFER_LENGTH); +} + +void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) { + va_list args; + va_start(args, fmt); + vsnprintf_P(lcd_status_message, STATUS_MESSAGE_BUFFER_LENGTH, fmt, args); + va_end(args); +} + +void lcd_setalertstatusPGM(const char * const message) { + lcd_setstatusPGM(message, 1); + GOTO_SCREEN(StatusScreen); +} + +void lcd_buttons_update() {} +inline void lcd_reset_alert_level() {} +inline bool lcd_detected() { return true; } +inline void lcd_refresh() {current_screen.onIdle();} diff --git a/Marlin/AO_UI_Framework.h b/Marlin/AO_UI_Framework.h new file mode 100644 index 000000000..e4d3becf7 --- /dev/null +++ b/Marlin/AO_UI_Framework.h @@ -0,0 +1,178 @@ +/**************************************************************************** + * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * To view a copy of the GNU General Public License, go to the following * + * location: . * + ****************************************************************************/ + + /********************** VIRTUAL DISPATCH DATA TYPE ******************************/ + +// True virtual classes are extremely expensive on the Arduino +// as the compiler stores the virtual function tables in RAM. +// We invent a data type called ScreenRef that gives us +// polymorphism by mapping an ID to virtual methods on various +// classes. This works by keeping a table in PROGMEM of pointers +// to static methods. + +#define DECL_SCREEN(className) { \ + className::onStartup, \ + className::onEntry, \ + className::onExit, \ + className::onIdle, \ + className::onRefresh, \ + className::onTouchStart, \ + className::onTouchHeld, \ + className::onTouchEnd \ +} + +#define GET_METHOD(type, method) reinterpret_cast(pgm_read_word_near(&functionTable[type].method##_ptr)) +#define SCREEN_TABLE PROGMEM const ScreenRef::table_t ScreenRef::functionTable[] = +#define SCREEN_TABLE_POST const uint8_t ScreenRef::functionTableSize = sizeof(ScreenRef::functionTable)/sizeof(ScreenRef::functionTable[0]); + +class ScreenRef { + protected: + typedef void onStartup_func_t(void); + typedef void onEntry_func_t(void); + typedef void onExit_func_t(void); + typedef void onIdle_func_t(void); + typedef void onRefresh_func_t(void); + typedef void onTouchStart_func_t(uint8_t); + typedef void onTouchHeld_func_t(uint8_t); + typedef void onTouchEnd_func_t(uint8_t); + + private: + typedef struct { + onStartup_func_t *onStartup_ptr; + onEntry_func_t *onEntry_ptr; + onExit_func_t *onExit_ptr; + onIdle_func_t *onIdle_ptr; + onRefresh_func_t *onRefresh_ptr; + onTouchStart_func_t *onTouchStart_ptr; + onTouchHeld_func_t *onTouchHeld_ptr; + onTouchEnd_func_t *onTouchEnd_ptr; + } table_t; + + uint8_t type = 0; + static PROGMEM const table_t functionTable[]; + static const uint8_t functionTableSize; + + public: + uint8_t getType() {return type;} + + void setType(uint8_t t) { + type = t; + } + + void setScreen(onEntry_func_t onRefresh_ptr) { + for(uint8_t type = 0; type < functionTableSize; type++) { + if(GET_METHOD(type, onRefresh) == onRefresh_ptr) { + setType(type); + #if defined(UI_FRAMEWORK_DEBUG) + #if defined(SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("New screen: ",type); + #else + Serial.print("New screen: "); + Serial.println(type); + #endif + #endif + return; + } + } + #if defined(UI_FRAMEWORK_DEBUG) + #if defined(SERIAL_PROTOCOLLNPAIR) + SERIAL_PROTOCOLLNPAIR("Screen not found: ", (uint16_t) onRefresh_ptr); + #else + Serial.print("Screen not found: "); + Serial.println((uint16_t) onRefresh_ptr, HEX); + #endif + #endif + } + + void onStartup() {GET_METHOD(type, onStartup)();} + void onEntry() {GET_METHOD(type, onEntry)();} + void onExit() {GET_METHOD(type, onExit)();} + void onIdle() {GET_METHOD(type, onIdle)();} + void onRefresh() {GET_METHOD(type, onRefresh)();} + void onTouchStart(uint8_t tag) {GET_METHOD(type, onTouchStart)(tag);} + void onTouchHeld(uint8_t tag) {GET_METHOD(type, onTouchHeld)(tag);} + void onTouchEnd(uint8_t tag) {GET_METHOD(type, onTouchEnd)(tag);} + + void initializeAll() { + for(uint8_t type = 0; type < functionTableSize; type++) { + GET_METHOD(type, onStartup)(); + } + } +}; + +/********************** SCREEN STACK ******************************/ + +// To conserve dynamic memory, the screen stack is hard-coded to +// have three values, allowing a menu of up to three levels. + +class ScreenStack : public ScreenRef { + private: + uint8_t stack[3]; + + public: + void start() { + initializeAll(); + onEntry(); + } + + void push() { + stack[2] = stack[1]; + stack[1] = stack[0]; + stack[0] = getType(); + } + + void pop() { + setType(stack[0]); + stack[0] = stack[1]; + stack[1] = stack[2]; + stack[2] = 0; + } + + void goTo(onEntry_func_t s) { + push(); + onExit(); + setScreen(s); + onEntry(); + } + + void goBack() { + pop(); + onEntry(); + } + + uint8_t getScreen() { + return getType(); + } +} current_screen; + +/********************** BASE SCREEN CLASSS ******************************/ + +/* UIScreen is the base class for all user interface screens. + */ +class UIScreen { + public: + static void onStartup() {} + static void onEntry() {current_screen.onRefresh();} + static void onExit() {} + static void onIdle() {} + static void onTouchStart(uint8_t) {} + static void onTouchHeld(uint8_t) {} + static void onTouchEnd(uint8_t) {} +}; + +#define GOTO_SCREEN(screen) current_screen.goTo(screen::onRefresh); +#define GOTO_PREVIOUS() current_screen.goBack(); diff --git a/Marlin/AO_UI_Marlin_LCD_API.h b/Marlin/AO_UI_Marlin_LCD_API.h new file mode 100644 index 000000000..2399e9a39 --- /dev/null +++ b/Marlin/AO_UI_Marlin_LCD_API.h @@ -0,0 +1,106 @@ +/**************************************************************************** + * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * To view a copy of the GNU General Public License, go to the following * + * location: . * + ****************************************************************************/ + +class Marlin_LCD_API { + public: + typedef const __FlashStringHelper *progmem_str; + + enum axis_t { + X, + Y, + Z, + E0, + E1 + }; + + static const uint8_t extruderCount; + static const uint8_t fanCount; + + static const float getActualTemp_celsius(const uint8_t extruder); + static const float getTargetTemp_celsius(const uint8_t extruder); + static const float getFan_percent(const uint8_t fan); + + static const float getAxisPosition_mm(const axis_t axis); + static const float getAxisSteps_per_mm(const axis_t axis); + static const uint8_t getProgress_percent(); + static const uint32_t getProgress_seconds_elapsed(); + static const uint8_t getFeedRate_percent(); + static const float getZOffset_mm(); + static const bool isAxisPositionKnown(const axis_t axis); +}; + +#if defined(MSG_MARLIN) +const uint8_t Marlin_LCD_API::extruderCount = EXTRUDERS; +const uint8_t Marlin_LCD_API::fanCount = 1; + +const float Marlin_LCD_API::getActualTemp_celsius(const uint8_t extruder) { + if(extruder) { + thermalManager.degHotend(extruder-1); + } else { + thermalManager.degBed(); + } +} + +const float Marlin_LCD_API::getTargetTemp_celsius(const uint8_t extruder) { + if(extruder) { + thermalManager.degTargetHotend(extruder-1); + } else { + thermalManager.degTargetBed(); + } +} + +const float Marlin_LCD_API::getFan_percent(const uint8_t fan) { + return ((fanSpeeds[fan] + 1) * 100) / 256; +} + +const float Marlin_LCD_API::getAxisPosition_mm(const Marlin_LCD_API::axis_t axis) { + switch(axis) { + case X: return current_position[X_AXIS]; break; + case Y: return current_position[Y_AXIS]; break; + case Z: return current_position[Z_AXIS]; break; + case E0: return current_position[E_AXIS]; break; + case E1: return current_position[E_AXIS+1]; break; + } +} + +const float Marlin_LCD_API::getAxisSteps_per_mm(const Marlin_LCD_API::axis_t axis) { + return 0; +} + +const uint8_t Marlin_LCD_API::getProgress_percent() { + #if ENABLED(SDSUPPORT) + return card.percentDone(); + #endif +} + +const uint32_t Marlin_LCD_API::getProgress_seconds_elapsed() { + const duration_t elapsed = print_job_timer.duration(); + return elapsed.value; +} + +const uint8_t Marlin_LCD_API::getFeedRate_percent() { + return feedrate_percentage; +} + +const bool Marlin_LCD_API::isAxisPositionKnown(const axis_t axis) { + switch(axis) { + case X: return axis_known_position[X_AXIS]; break; + case Y: return axis_known_position[Y_AXIS]; break; + case Z: return axis_known_position[Z_AXIS]; break; + } +} +#endif \ No newline at end of file diff --git a/Marlin/Conditionals_LulzBot.h b/Marlin/Conditionals_LulzBot.h index 0ca7868be..ab20b058b 100644 --- a/Marlin/Conditionals_LulzBot.h +++ b/Marlin/Conditionals_LulzBot.h @@ -13,7 +13,7 @@ * got disabled. */ -#define LULZBOT_FW_VERSION ".4" // Change this with each update +#define LULZBOT_FW_VERSION ".5" // Change this with each update #if ( \ !defined(LULZBOT_Gladiola_Mini) && \ @@ -21,7 +21,9 @@ !defined(LULZBOT_Juniper_TAZ5) && \ !defined(LULZBOT_Oliveoil_TAZ6) && \ !defined(LULZBOT_Hibiscus_Mini2) && \ - !defined(LULZBOT_Quiver_TAZ7) \ + !defined(LULZBOT_Hibiscus_Mini2_CLCD) && \ + !defined(LULZBOT_Quiver_TAZ7) && \ + !defined(LULZBOT_Quiver_TAZ7_CLCD) \ ) || ( \ !defined(TOOLHEAD_Gladiola_SingleExtruder) && \ !defined(TOOLHEAD_Albatross_Flexystruder) && \ @@ -120,6 +122,26 @@ #define LULZBOT_USE_EXPERIMENTAL_FEATURES #endif +#if defined(LULZBOT_Hibiscus_Mini2_CLCD) + #define LULZBOT_CUSTOM_MACHINE_NAME "LulzBot Mini 2" + #define LULZBOT_LCD_MACHINE_NAME "Mini 2" + #define LULZBOT_IS_MINI + #define LULZBOT_MINI_BED + #define LULZBOT_USE_EINSYRAMBO + #define LULZBOT_USE_EINSY_RETRO + #define LULZBOT_USE_TOUCH_UI + #define LULZBOT_TWO_PIECE_BED + #define LULZBOT_USE_AUTOLEVELING + #define LULZBOT_SENSORLESS_HOMING + #define LULZBOT_USE_TMC_STEALTHCHOP_Z + #define LULZBOT_USE_Z_BELT + #define LULZBOT_BAUDRATE 250000 + #define LULZBOT_PRINTCOUNTER + #define LULZBOT_USE_32_MICROSTEPS_ON_Z + #define LULZBOT_UUID "e5502411-d46d-421d-ba3a-a20126d7930f" + #define LULZBOT_USE_EXPERIMENTAL_FEATURES +#endif + #if defined(LULZBOT_Quiver_TAZ7) #define LULZBOT_CUSTOM_MACHINE_NAME "LulzBot TAZ 7" #define LULZBOT_LCD_MACHINE_NAME "TAZ 7" @@ -139,6 +161,24 @@ #define LULZBOT_USE_EXPERIMENTAL_FEATURES #endif +#if defined(LULZBOT_Quiver_TAZ7_CLCD) + #define LULZBOT_CUSTOM_MACHINE_NAME "LulzBot TAZ 7" + #define LULZBOT_LCD_MACHINE_NAME "TAZ 7" + #define LULZBOT_IS_TAZ + #define LULZBOT_TAZ_BED + #define LULZBOT_TWO_PIECE_BED + #define LULZBOT_USE_TOUCH_UI + #define LULZBOT_USE_AUTOLEVELING + #define LULZBOT_USE_MIN_ENDSTOPS + #define LULZBOT_USE_MAX_ENDSTOPS + #define LULZBOT_USE_NORMALLY_CLOSED_ENDSTOPS + #define LULZBOT_USE_Z_BELT + #define LULZBOT_BAUDRATE 250000 + #define LULZBOT_PRINTCOUNTER + #define LULZBOT_UUID "a952577d-8722-483a-999d-acdc9e772b7b" + #define LULZBOT_USE_EXPERIMENTAL_FEATURES +#endif + /****************************** DEBUGGING OPTIONS *******************************/ //#define LULZBOT_TMC_SHOW_CURRENT_ADJUSTMENTS @@ -1875,6 +1915,11 @@ #define LULZBOT_LCD_CLEAR_DECL #endif +#if defined(LULZBOT_USE_TOUCH_UI) +extern void lcd_update(); +extern void lcd_buttons_update(); +#endif + /***************************** CUSTOM SPLASH SCREEN *****************************/ #define LULZBOT_CUSTOM_BOOTSCREEN() \ diff --git a/Marlin/Configuration_LulzBot.h b/Marlin/Configuration_LulzBot.h index 972317d67..b13155c1c 100644 --- a/Marlin/Configuration_LulzBot.h +++ b/Marlin/Configuration_LulzBot.h @@ -13,9 +13,11 @@ Gladiola_Mini // Lulzbot Mini (Gladiola) Gladiola_MiniLCD // Lulzbot Mini (Gladiola w/ LCD) Hibiscus_Mini2 // Lulzbot Mini 2 (Hibiscus) + Hibiscus_Mini2_CLCD // Lulzbot Mini 2 (Hibiscus w/ CLCD) Juniper_TAZ5 // Lulzbot TAZ 5 (Juniper, Juniperberry, Juniperbush) Oliveoil_TAZ6 // Lulzbot TAZ 6 (Oliveoil) Quiver_TAZ7 // Lulzbot TAZ 7 (Quiver) + Quiver_TAZ7_CLCD // Lulzbot TAZ 7 (Quiver w/ CLCD) Mini Toolhead Choices: Gladiola_SingleExtruder // Standard Single Extruder (Gladiola) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 29c04b2ee..f2f137f2c 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -348,6 +348,21 @@ float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ]; #endif +#if defined(LULZBOT_USE_TOUCH_UI) +#define IS_FT810 +#define LCD_PORTRAIT +#define LCD_UPSIDE_DOWN +//#define UI_FRAMEWORK_DEBUG +#include "AO_UI_Marlin_LCD_API.h" +#include "AO_UI_Framework.h" +#include "AO_FT810_Constants.h" +#include "AO_FT810_Functions.h" +#include "AO_FT810_Pins.h" +#include "AO_FT810_SPI.h" +#include "AO_FT810_UI_Bitmaps.h" +#include "AO_FT810_UI_Screens.h" +#endif + bool Running = true; uint8_t marlin_debug_flags = DEBUG_NONE; diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index ab2ce15a3..a8ca159fb 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -185,8 +185,7 @@ extern uint8_t progress_bar_percent; #endif -#else // no LCD - +#elif !defined(LULZBOT_USE_TOUCH_UI) // no LCD inline void lcd_update() {} inline void lcd_init() {} inline bool lcd_hasstatus() { return false; } @@ -198,7 +197,6 @@ inline void lcd_reset_alert_level() {} inline bool lcd_detected() { return true; } inline void lcd_refresh() {} - #endif // ULTRA_LCD #define LCD_MESSAGEPGM(x) lcd_setstatusPGM(PSTR(x))