From 4dc9422923cdc2a128294c5c3690bb702951e63e Mon Sep 17 00:00:00 2001 From: maggi Date: Thu, 20 Aug 2020 16:16:56 +0200 Subject: [PATCH] Initial commit --- Maiskolben_TFT.ino | 1046 +++++++++++++++++++++++++++++++++++++++++ TFT_ILI9163C.cpp | 1114 ++++++++++++++++++++++++++++++++++++++++++++ definitions.h | 195 ++++++++ keywords.txt | 21 + library.properties | 9 + 5 files changed, 2385 insertions(+) create mode 100644 Maiskolben_TFT.ino create mode 100644 TFT_ILI9163C.cpp create mode 100644 definitions.h create mode 100644 keywords.txt create mode 100644 library.properties diff --git a/Maiskolben_TFT.ino b/Maiskolben_TFT.ino new file mode 100644 index 0000000..65c3a5c --- /dev/null +++ b/Maiskolben_TFT.ino @@ -0,0 +1,1046 @@ +#include +#include +#include +#include +#include +#include "definitions.h" + +/* + If your display stays white, uncomment this. + Cut reset trace (on THT on upper layer/0R), connect STBY_NO (A1) with reset of TFT (at 4050). + See also readme in mechanical folder for reference. +*/ + #define USE_TFT_RESET // Benötigt + +/* + If red is blue and blue is red change this + If not sure, leave commented, you will be shown a setup screen +*/ +// #define HARDWARE_DEFINED_TFT 2 +/* + Based on your Hardware-Revision there may be modifications to the PCB. + In V3 and up is a second voltage measurement circuit. + HW REVS: + 1.5 - 2.8: + For THT this should be set to anything < 3 + Normally leave this commented as it is stored in EEPROM +*/ + +// V 1.5 - 2.11, Maiskolben THT2 +//#define HARDWARE_REVISION 2 +// V 3.0 and 3.1 +//#define HARDWARE_REVISION 3 + +/* + Only used for testing, do not use. +*/ +// #define INSTALL +// #define TEST_ADC + +volatile boolean off = true, stby = true, stby_layoff = false, sw_stby_old = false, sw_up_old = false, sw_down_old = false, clear_display = true, store_invalid = true, menu = false; +volatile uint8_t pwm, threshold_counter; +volatile int16_t cur_t, last_measured; +volatile error_type error = NO_ERROR; +error_type error_old; +int16_t stored[3] = {300, 350, 450}, set_t = TEMP_MIN, set_t_old, cur_t_old, target_t; +double pid_val, cur_td, set_td; +uint8_t store_to = 255; +p_source power_source, power_source_old = NO_INIT; +boolean blink; +uint16_t cnt_measure_voltage, cnt_compute, cnt_sw_poll, cnt_but_press, cnt_off_press, cnt_but_store; +float v_c1, v_c2, v_c3, v_in, v; +uint8_t array_index, array_count; +uint32_t sendNext; +uint32_t last_temperature_drop; +uint32_t last_on_state; +boolean wasOff = true, old_stby = false; +boolean autopower = true, bootheat = false, fahrenheit = false; +uint8_t revision = 1; +boolean menu_dismissed = false; +boolean autopower_repeat_under = false; +boolean force_redraw = false; +boolean power_down = false; +uint16_t charge = 0; +float adc_offset = ADC_TO_TEMP_OFFSET; +float adc_gain = ADC_TO_TEMP_GAIN; + +#define RGB_DISP 0x0 +#define BGR_DISP 0x2 + +#ifdef USE_TFT_RESET +TFT_ILI9163C tft = TFT_ILI9163C(TFT_CS, TFT_DC, STBY_NO); +#else +TFT_ILI9163C tft = TFT_ILI9163C(TFT_CS, TFT_DC); +#endif + +#define BLACK 0x0000 +#define RED 0x001F // Blue +#define BLUE 0xF800 // Red +#define GREEN 0x07E0 +#define YELLOW 0x07FF // Cyan +#define MAGENTA 0xF81F +#define CYAN 0xFFE0 // Yellow +#define WHITE 0xFFFF +#define GRAY 0x94B2 + +PID heaterPID(&cur_td, &pid_val, &set_td, kp, ki, kd, DIRECT); + +void setup(void) { + digitalWrite(HEATER_PWM, LOW); + pinMode(HEATER_PWM, OUTPUT); + pinMode(POWER, INPUT_PULLUP); + pinMode(HEAT_LED, OUTPUT); + digitalWrite(HEAT_LED, HIGH); + pinMode(TEMP_SENSE, INPUT); + pinMode(SW_T1, INPUT_PULLUP); + pinMode(SW_T2, INPUT_PULLUP); + pinMode(SW_T3, INPUT_PULLUP); + pinMode(SW_UP, INPUT_PULLUP); + pinMode(SW_DOWN, INPUT_PULLUP); + pinMode(STBY_NO, INPUT_PULLUP); + pinMode(SW_STBY, INPUT_PULLUP); + pinMode(TFT_CS, OUTPUT); + digitalWrite(TFT_CS, HIGH); + Serial.begin(115200); + + boolean force_menu = false; + if (EEPROM.read(0) != EEPROM_CHECK) { + EEPROM.update(0, EEPROM_CHECK); + updateEEPROM(); + force_menu = true; + } + tft.begin(); +#ifdef HARDWARE_DEFINED_TFT +#if HARDWARE_DEFINED_TFT == 1 + EEPROM.update(EEPROM_DISPLAY, RGB_DISP); + setDisplayMode(0); +#else + EEPROM.update(EEPROM_DISPLAY, BGR_DISP); + setDisplayMode(1); +#endif +#else + if (force_menu || EEPROM.read(EEPROM_VERSION) < 23 || EEPROM.read(EEPROM_VERSION) == 255 || (EEPROM.read(EEPROM_DISPLAY) != BGR_DISP && EEPROM.read(EEPROM_DISPLAY) != RGB_DISP)) { + tft.fillScreen(BLACK); + setDisplayMode(1); + tft.setTextSize(2); + tft.setCursor(0, 0); + tft.setTextColor(WHITE); + tft.print(F("What color is displayed?")); + tft.setCursor(10, 112); + tft.setTextColor(RED); + tft.print("RED BLUE"); + while (true) { + if (!digitalRead(SW_T1)) { + EEPROM.update(EEPROM_DISPLAY, BGR_DISP); + setDisplayMode(1); + break; + } + if (!digitalRead(SW_T3)) { + EEPROM.update(EEPROM_DISPLAY, RGB_DISP); + setDisplayMode(0); + break; + } + } + tft.fillScreen(BLACK); + tft.setTextColor(YELLOW); + tft.drawBitmap(0, 20, maiskolben, 160, 64, YELLOW); + tft.setCursor(20, 86); + tft.setTextColor(YELLOW); + tft.setTextSize(2); + tft.print("Maiskolben"); + tft.setCursor(35, 104); + tft.print("Welcome!"); + delay(4000); + while (!digitalRead(SW_T3) || !digitalRead(SW_T1)) delay(100); + } else { + setDisplayMode(EEPROM.read(EEPROM_DISPLAY) == BGR_DISP); + } +#endif +#ifdef INSTALL + if (EEPROM.read(EEPROM_INSTALL) != EEPROM_CHECK) { + tft.fillScreen(BLACK); + tft.setTextColor(RED, BLACK); + tft.setCursor(0, 0); + tft.setTextSize(2); + tft.println("Installation"); + for (int16_t i = -255; i < 256; i++) { + analogWrite(HEAT_LED, 255 - abs(i)); + delay(1); + } + uint16_t adc1 = 0, adc2 = 0; + while (digitalRead(SW_STBY)) { + int t = getTemperature(); + uint16_t adc = analogRead(TEMP_SENSE); + Serial.println(t); + digitalWrite(HEATER_PWM, !digitalRead(SW_T1) | !digitalRead(SW_T2) | !digitalRead(SW_T3)/* | !digitalRead(SW_UP) | !digitalRead(SW_DOWN)*/); + if (!digitalRead(SW_DOWN)) { + if (!adc) { + digitalWrite(HEATER_PWM, HIGH); + } else { + adc1 = adc; + } + } + if (!digitalRead(SW_UP)) { + if (!adc) { + digitalWrite(HEATER_PWM, HIGH); + } else { + adc2 = adc; + } + } + tft.setCursor(0, 18); + tft.print(t); + tft.println(" "); + tft.print(adc); + tft.println(" "); + tft.println(adc * adc_gain + adc_offset); + if (adc1 != 0 && adc2 != 0) { + adc_gain = DELTA_REF_T / (float)(adc2 - adc1); + adc_offset = REF_T1 - adc_gain * adc1; + tft.println(adc_gain); + tft.println(adc_offset); + } + delay(50); + } + EEPROM.update(EEPROM_OPTIONS, (fahrenheit << 2) | (bootheat << 1) | autopower); + EEPROM.update(EEPROM_VERSION, EE_VERSION); + EEPROM.update(EEPROM_INSTALL, EEPROM_CHECK); + EEPROM.put(EEPROM_ADCTTG, adc_gain); + EEPROM.put(EEPROM_ADCOFF, adc_offset); + + tft.println("done."); + delay(1000); + asm volatile("jmp 0"); + } +#endif + if (EEPROM.read(EEPROM_VERSION) != EE_VERSION) { + force_menu = true; + } + tft.fillScreen(BLACK); + uint8_t options = EEPROM.read(EEPROM_OPTIONS); + autopower = options & 1; + bootheat = options & 2; + fahrenheit = options & 4; + if (force_menu) { + optionMenu(); + } else { + updateRevision(); + tft.drawBitmap(0, 20, maiskolben, 160, 64, YELLOW); + tft.setCursor(20, 86); + tft.setTextColor(YELLOW); + tft.setTextSize(2); + tft.print("Maiskolben"); + tft.setCursor(50, 110); + tft.setTextSize(1); + tft.print("Version "); + tft.print(VERSION); + tft.setCursor(46, 120); + tft.print("HW Revision "); + tft.print(revision); + //Allow Options to be set at startup + delay(100); + attachInterrupt(digitalPinToInterrupt(SW_STBY), optionMenu, LOW); + for (int i = 0; i < 10 && !menu_dismissed; i++) { + digitalWrite(HEAT_LED, i % 2); + delay(250); + } + detachInterrupt(digitalPinToInterrupt(SW_STBY)); + } + /* + lower frequency = noisier tip + higher frequency = needs higher pwm + */ + //PWM Prescaler = 1024 31Hz + //TCCR2B = (TCCR2B & 0b11111000) | 7; + //PWM Prescaler = 256 122Hz + //TCCR2B = (TCCR2B & 0b11111000) | 6; + //PWM Prescaler = 128 245Hz + //TCCR2B = (TCCR2B & 0b11111000) | 5; // Orginal + //PWM Prescaler = 64 490Hz + //TCCR2B = (TCCR2B & 0b11111000) | 4; + //PWM Prescaler = 32 980Hz + //TCCR2B = (TCCR2B & 0b11111000) | 3; + //PWM Prescaler = 8 3.9kHz + //TCCR2B = (TCCR2B & 0b11111000) | 2 + //PWM Prescaler = 1 31kHz - no Noise + TCCR2B = (TCCR2B & 0b11111000) | 1; + stby = EEPROM.read(1); + for (uint8_t i = 0; i < 3; i++) { + stored[i] = EEPROM.read(2 + i * 2) << 8; + stored[i] |= EEPROM.read(3 + i * 2); + } + set_t = EEPROM.read(EEPROM_SET_T) << 8; + set_t |= EEPROM.read(EEPROM_SET_T + 1); + + for (uint8_t i = 0; i < 50; i++) + measureVoltage(); //measure average 50 times to get realistic results + + tft.fillScreen(BLACK); + for (uint8_t i = 0; i <= 160; i++) { // Fix for remaining Corn-Bitmap + tft.drawFastVLine(i,0,128,BLACK); + } + last_measured = getTemperature(); + Timer1.initialize(1000); + Timer1.attachInterrupt(timer_isr); + heaterPID.SetMode(AUTOMATIC); + sendNext = millis(); + if (bootheat) { + threshold_counter = TEMP_UNDER_THRESHOLD; + setOff(false); + } + if (EEPROM.read(EEPROM_ADCTTG) == 255) { //Override unset values from older versions + EEPROM.put(EEPROM_ADCTTG, adc_gain); + EEPROM.put(EEPROM_ADCOFF, adc_offset); + } + EEPROM.get(EEPROM_ADCTTG, adc_gain); + EEPROM.get(EEPROM_ADCOFF, adc_offset); +} + +void updateRevision(void) { +#if (HARDWARE_REVISION > 2) + EEPROM.update(EEPROM_REVISION, HARDWARE_REVISION); + revision = 3; +#else + if (EEPROM.read(EEPROM_VERSION) < 26 || EEPROM.read(EEPROM_REVISION) > 100) { + EEPROM.update(EEPROM_REVISION, 2); + revision = 2; + } else { + revision = EEPROM.read(EEPROM_REVISION); + } +#endif +} + +void setDisplayMode(boolean bgr) { + // tft.colorSpace(bgr); + tft.setRotation(1); // 3 +} + +void optionMenu(void) { + tft.fillScreen(BLACK); + digitalWrite(HEAT_LED, LOW); + tft.setTextSize(2); + tft.setCursor(0, 0); + tft.setTextColor(WHITE); + tft.println("Options\n"); + tft.setTextColor(WHITE); + tft.setCursor(10, 112); + tft.print("ON OFF EXIT"); + uint8_t options = 3; + uint8_t opt = 0; + boolean redraw = true; + while (true) { + if (redraw) { + tft.setCursor(0, 36); +#ifdef SHUTOFF_ACTIVE + tft.setTextColor(autopower ? GREEN : RED); +#else + tft.setTextColor(GRAY); +#endif + tft.println(" Autoshutdown"); +#ifdef BOOTHEAT_ACTIVE + tft.setTextColor(bootheat ? GREEN : RED); +#else + tft.setTextColor(GRAY); +#endif + tft.println(" Heat on boot"); + tft.setTextColor(fahrenheit ? GREEN : RED); + tft.println(" Fahrenheit"); + + tft.setCursor(0, (opt + 2) * 18); + tft.setTextColor(WHITE); + tft.print(">"); + redraw = false; + } + if (!digitalRead(SW_UP)) { + tft.setCursor(0, (opt + 2) * 18); + tft.setTextColor(BLACK); + tft.print(">"); + opt = (opt + options - 1) % options; + while (!digitalRead(SW_UP)) delay(100); + redraw = true; + } + if (!digitalRead(SW_DOWN)) { + tft.setCursor(0, (opt + 2) * 18); + tft.setTextColor(BLACK); + tft.print(">"); + opt = (opt + 1) % options; + while (!digitalRead(SW_DOWN)) delay(100); + redraw = true; + } + if (!digitalRead(SW_T1)) { + switch (opt) { + case 0: autopower = 1; break; + case 1: bootheat = 1; break; + case 2: fahrenheit = 1; break; + } + redraw = true; + } + if (!digitalRead(SW_T2)) { + switch (opt) { + case 0: autopower = 0; break; + case 1: bootheat = 0; break; + case 2: fahrenheit = 0; break; + } + redraw = true; + } + if (!digitalRead(SW_T3)) { + break; + } + } + EEPROM.update(EEPROM_OPTIONS, (fahrenheit << 2) | (bootheat << 1) | autopower); + updateRevision(); + EEPROM.update(EEPROM_VERSION, EE_VERSION); + if (EEPROM.read(EEPROM_VERSION) < 30) { + EEPROM.put(EEPROM_ADCTTG, ADC_TO_TEMP_GAIN); + EEPROM.put(EEPROM_ADCOFF, ADC_TO_TEMP_OFFSET); + } + menu_dismissed = true; +} + +void updateEEPROM(void) { + EEPROM.update(1, stby); + for (uint8_t i = 0; i < 3; i++) { + EEPROM.update(2 + i * 2, stored[i] >> 8); + EEPROM.update(3 + i * 2, stored[i] & 0xFF); + } + EEPROM.update(8, set_t >> 8); + EEPROM.update(9, set_t & 0xFF); + EEPROM.update(EEPROM_OPTIONS, (fahrenheit << 2) | (bootheat << 1) | autopower); +} + +void powerDown(void) { + if (power_source != POWER_LIPO) { + power_down = false; + return; + } + //Timer1.stop(); + setOff(true); + delay(10); + tft.fillScreen(BLACK); + tft.setTextSize(4); + tft.setTextColor(RED); + tft.setCursor(50, 40); + tft.print("OFF"); + delay(3000); + SPI.end(); + digitalWrite(POWER, LOW); + pinMode(POWER, OUTPUT); + delay(100); + force_redraw = true; + power_down = false; + Timer1.start(); //unsuccessful +} + +float toFahrenheit(float t) { + return t * 1.8 + 32; +} + +int getTemperature(void) { + analogRead(TEMP_SENSE);//Switch ADC MUX + uint16_t adc = median(TEMP_SENSE); +#ifdef TEST_ADC + Serial.println(adc); +#endif + if (adc >= 900) { //Illegal value, tip not plugged in - would be around 560deg + analogWrite(HEATER_PWM, 0); + if (!off) { + setError(NO_TIP); + return 999; + } + } else { + analogWrite(HEATER_PWM, pwm); //switch heater back to last value + } + //return round(adc < 210 ? (((float)adc) * 0.530805 + 38.9298) : (((float)adc) * 0.415375 + 64.6123)); //old conversion + return round(((float) adc) * adc_gain + adc_offset); +} + +void measureVoltage(void) { + analogRead(BAT_C1); //Switch analog MUX before measuring + v_c1 = v_c1 * .9 + (analogRead(BAT_C1) * 5 / 1024.0) * .1; //no divisor + analogRead(BAT_C2); + v_c2 = v_c2 * .9 + (analogRead(BAT_C2) * 5 / 512.0) * .1; //divisor 1:1 -> /2 + analogRead(BAT_C3); + v_c3 = v_c3 * .9 + (analogRead(BAT_C3) * (5.0 * 3.0) / 1024.0) * .1; //maximum measurable is ~15V + v = v_c3; + if (revision < 3) { + return; + } +#ifdef VIN + analogRead(VIN); + v_in = v_in * .9 + (analogRead(VIN) * 25 / 1024.0) * .1; //maximum measurable is ~24.5V + v = v_in; //backwards compatibility +#endif +} + +uint16_t median(uint8_t analogIn) { + uint16_t adcValue[3]; + for (uint8_t i = 0; i < 3; i++) { + adcValue[i] = analogRead(analogIn); // read the input 3 times + } + uint16_t tmp; + if (adcValue[0] > adcValue[1]) { + tmp = adcValue[0]; + adcValue[0] = adcValue[1]; + adcValue[1] = tmp; + } + if (adcValue[1] > adcValue[2]) { + tmp = adcValue[1]; + adcValue[1] = adcValue[2]; + adcValue[2] = tmp; + } + if (adcValue[0] > adcValue[1]) { + tmp = adcValue[0]; + adcValue[0] = adcValue[1]; + adcValue[1] = tmp; + } + return adcValue[1]; +} + +void timer_sw_poll(void) { + if (power_down) { + return; + } + if (!digitalRead(SW_STBY)) { + if (cnt_off_press == 100) { + setOff(!off); + } + if (cnt_off_press == 200 && power_source == POWER_LIPO) { + setOff(true); + power_down = true; + return; + } + cnt_off_press = min(201, cnt_off_press + 1); + } else { + if (cnt_off_press > 0 && cnt_off_press <= 100) { + setStandby(!stby); + } + cnt_off_press = 0; + } + boolean t1 = !digitalRead(SW_T1); + boolean t2 = !digitalRead(SW_T2); + boolean t3 = !digitalRead(SW_T3); + + //simultanious push of multiple buttons + if (t1 + t2 + t3 > 1) { + store_to = 255; + store_invalid = true; + } else if (error != NO_ERROR) { + if (!(t1 | t2 | t3)) { + store_invalid = false; + } else if (!store_invalid && t3) { + error = NO_ERROR; //dismiss + set_t_old = 0; //refresh set_t display + store_invalid = true; //wait for release + } + } else { + //all buttons released + if (!(t1 | t2 | t3)) { + if (store_to != 255) { + if (cnt_but_store <= 100) { + set_t = stored[store_to]; + setStandby(false); + updateEEPROM(); + } + } + store_to = 255; + store_invalid = false; + cnt_but_store = 0; + } else + //one button pressed + if (!store_invalid) { + store_to = t2 + 2 * t3; + if (cnt_but_store > 100) { + if (set_t != stored[store_to] && !stby) { + stored[store_to] = set_t; + cnt_but_store = 100; + updateEEPROM(); + } + } + cnt_but_store++; + } + } + boolean sw_up = !digitalRead(SW_UP); + boolean sw_down = !digitalRead(SW_DOWN); + boolean sw_changed = (sw_up != sw_up_old) || (sw_down != sw_down_old); + sw_up_old = sw_up; + sw_down_old = sw_down; + if ((sw_up && sw_down) || !(sw_up || sw_down)) { + cnt_but_press = 0; + return; + } + if (sw_up || sw_down) { + cnt_but_press++; + if ((cnt_but_press >= 100) || sw_changed) { + setStandby(false); + if (sw_up && set_t < TEMP_MAX) { + set_t++; + } + else if (sw_down && set_t > TEMP_MIN) { + set_t--; + } + if (!sw_changed) { + cnt_but_press = 97; + } + updateEEPROM(); + } + } +} + +void setStandby(boolean state) { + if (stby_layoff) { + return; + } + if (state == stby) { + return; + } + stby = state; + last_measured = cur_t; + last_temperature_drop = millis(); + last_on_state = millis() / 1000; + EEPROM.update(1, stby); +} + +void setStandbyLayoff(boolean state) { + if (state == stby_layoff) { + return; + } + stby_layoff = state; + stby = false; + last_measured = cur_t; + last_on_state = millis() / 1000; +} + +void setOff(boolean state) { + if (state == off) { + return; + } + if (!state) { + analogWrite(HEATER_PWM, 0); + } else { + setStandby(false); + } + if (power_source == POWER_USB && !state) { + state = true; //don't switch on, if powered via USB + setError(USB_ONLY); + } + last_on_state = millis() / 1000; + off = state; + wasOff = true; + last_measured = cur_t; +} + +void printTemp(float t) { + if (fahrenheit) { + t = toFahrenheit(t); + } + if (t < 100) { + tft.write(' '); + } + tft.print((int)t); +} + +void display(void) { + if (force_redraw) { + tft.fillScreen(BLACK); + } + int16_t temperature = cur_t; //buffer volatile value + boolean yell = stby || (stby_layoff && blink); + tft.drawCircle(20, 63, 8, off ? RED : yell ? YELLOW : GREEN); + tft.drawCircle(20, 63, 7, off ? RED : yell ? YELLOW : GREEN); + tft.fillRect(19, 55, 3, 3, BLACK); + tft.drawFastVLine(20, 53, 10, off ? RED : yell ? YELLOW : GREEN); + if (error != NO_ERROR) { + if (error != error_old || force_redraw) { + error_old = error; + tft.setTextSize(1); + tft.setTextColor(RED, BLACK); + tft.setCursor(0, 96); + switch (error) { + case EXCESSIVE_FALL: + tft.print(F("Error: Temperature dropped\nTip slipped out?")); + break; + case NOT_HEATING: + tft.print(F("Error: Not heating\nWeak power source or short")); + break; + case BATTERY_LOW: + tft.print(F("Error: Battery low\nReplace or charge")); + break; + case USB_ONLY: + tft.print(F("Error: Power too low\nConnect power >5V")); + break; + case NO_TIP: + tft.print(F("Error: No tip connected\nTip slipped out?")); + break; + } + tft.setTextSize(2); + tft.setTextColor(YELLOW, BLACK); + tft.setCursor(10, 112); + tft.print(F(" OK ")); + + tft.setTextColor(RED, BLACK); + tft.setCursor(36, 26); + tft.setTextSize(3); + tft.print(F(" ERR ")); + } + } else { + if (error != error_old || force_redraw) { + tft.fillRect(0, 96, 160, 16, BLACK); + error_old = NO_ERROR; + } + tft.setTextSize(2); + tft.setCursor(15, 112); + tft.setTextColor(WHITE, BLACK); + printTemp(stored[0]); + tft.write(' '); + printTemp(stored[1]); + tft.write(' '); + printTemp(stored[2]); + + if (set_t_old != set_t || old_stby != (stby || stby_layoff) || force_redraw) { + tft.setCursor(36, 26); + tft.setTextSize(3); + if (stby || stby_layoff) { + old_stby = true; + tft.setTextColor(YELLOW, BLACK); + tft.print(F("STBY ")); + } else { + old_stby = false; + set_t_old = set_t; + tft.setTextColor(WHITE, BLACK); + tft.write(' '); + printTemp(set_t); + tft.write(247); + tft.write(fahrenheit ? 'F' : 'C'); + tft.fillTriangle(149, 50, 159, 50, 154, 38, (set_t < TEMP_MAX) ? WHITE : GRAY); + tft.fillTriangle(149, 77, 159, 77, 154, 90, (set_t > TEMP_MIN) ? WHITE : GRAY); + } + } + if (!off) { +#ifdef SHUTOFF_ACTIVE + if (autopower) { + int16_t tout; + if (stby || stby_layoff) { + tout = min(max(0, (last_on_state + OFF_TIMEOUT - (millis()) / 1000)), OFF_TIMEOUT); + } else { + tout = min(max(0, (last_temperature_drop + STANDBY_TIMEOUT - (millis()) / 1000)), STANDBY_TIMEOUT); + } + tft.setTextColor(stby ? RED : YELLOW, BLACK); + tft.setTextSize(2); + tft.setCursor(46, 78); + if (tout < 600) { + tft.write('0'); + } + tft.print(tout / 60); + tft.write(':'); + if (tout % 60 < 10) { + tft.write('0'); + } + tft.print(tout % 60); + } +#endif + } else if (temperature != 999) { + tft.fillRect(46, 78, 60, 20, BLACK); + } + } + if (cur_t_old != temperature || force_redraw) { + tft.setCursor(36, 52); + tft.setTextSize(3); + if (temperature == 999) { + tft.setTextColor(RED, BLACK); + tft.print(F(" ERR ")); + tft.setCursor(44, 76); + tft.setTextSize(2); + tft.print(F("NO TIP")); + } else { + if (cur_t_old == 999) { + tft.fillRect(44, 76, 72, 16, BLACK); + } + tft.setTextColor(off ? temperature < TEMP_COLD ? CYAN : RED : tft.Color565(min(10, abs(temperature - target_t)) * 25, 250 - min(10, max(0, (abs(temperature - target_t) - 10))) * 25, 0), BLACK); + if (temperature < TEMP_COLD) { + tft.print(F("COLD ")); + } else { + tft.write(' '); + printTemp(temperature); + tft.write(247); + tft.write(fahrenheit ? 'F' : 'C'); + } + } + if (temperature < cur_t_old) { + tft.fillRect(max(0, (temperature - TEMP_COLD) / 2.4), 0, 160 - max(0, (temperature - TEMP_COLD) / 2.4), BAR_HEIGHT, BLACK); + } else if (cur_t != 999) { + for (int16_t i = max(0, (cur_t_old - TEMP_COLD) / 2.4); i < max(0, (temperature - TEMP_COLD) / 2.4); i++) { + tft.drawFastVLine(i, 0, BAR_HEIGHT, tft.Color565(min(255, max(0, i * 5)), min(255, max(0, 450 - i * 2.5)), 0)); + } + } + cur_t_old = temperature; + } + if (v_c3 > 1.0) { + tft.setTextColor(YELLOW, BLACK); + tft.setCursor(122, 5); + tft.setTextSize(2); + int power = min(15, v) * min(15, v) / 4.8 * pwm / 255; + if (power < 10) { + tft.write(' '); + } + tft.print(power); + tft.write('W'); + + if (v < 5.0) { + power_source = POWER_USB; + } else if (v_c2 < 1.0) { + power_source = POWER_CORD; + } else { + power_source = POWER_LIPO; //Set charging later to not redraw if charging mode toggles + } + if (power_source != power_source_old || force_redraw) { + tft.fillRect(0, 5, 128, 20, BLACK); + tft.fillRect(11, 25, 21, 20, BLACK); + switch (power_source) { + case POWER_CHARGING: + case POWER_LIPO: + for (uint8_t i = 0; i < 3; i++) { + tft.drawRect(11, 5 + i * 14, 20, 12, WHITE); + //tft.fillRect(12, 6+i*14, 18, 10, BLACK); + tft.drawFastVLine(31, 8 + i * 14, 6, WHITE); + } + break; + case POWER_USB: + tft.setTextSize(1); + tft.setTextColor(RED, BLACK); + tft.setCursor(0, 5); + tft.print("USB power only\nConnect power supply."); + if (!off) { + setError(USB_ONLY); + } + break; + } + power_source_old = power_source; + } + if (power_source == POWER_CORD) { + /*if (v > v_c3) { + tft.setTextSize(2); + tft.setTextColor(GREEN, BLACK); + tft.setCursor(0,5); + tft.print(v); + tft.print("V "); + } else {*/ + tft.drawBitmap(0, 5, power_cord, 24, 9, tft.Color565(max(0, min(255, (14.5 - v) * 112)), max(0, min(255, (v - 11) * 112)), 0)); + //} + } else if (power_source == POWER_LIPO || power_source == POWER_CHARGING) { + float volt[] = {v_c1, v_c2 - v_c1, v_c3 - v_c2}; + uint8_t volt_disp[] = {max(1, min(16, (volt[0] - 3.0) * 14.2)), max(1, min(16, (volt[1] - 3.0) * 14.2)), max(1, min(16, (volt[2] - 3.0) * 14.2))}; + if (power_source == POWER_CHARGING) { + uint8_t p = min(16, (millis() / 100) % 20); + for (uint8_t i = 0; i < 3; i++) { + volt_disp[i] = max(0, min(volt_disp[i], p)); + } + } + for (uint8_t i = 0; i < 3; i++) { + if (volt[i] < 3.20) { + setError(BATTERY_LOW); + tft.fillRect(13, 7 + 14 * i, volt_disp[i], 8, blink ? RED : BLACK); + } else { + tft.fillRect(13, 7 + 14 * i, volt_disp[i], 8, tft.Color565(250 - min(250, max(0, (volt[i] - 3.4) * 1000.0)), max(0, min(250, (volt[i] - 3.15) * 1000.0)), 0)); + } + tft.fillRect(13 + volt_disp[i], 7 + 14 * i, 17 - volt_disp[i], 8, BLACK); + } + } + } +#ifdef SHUTOFF_ACTIVE + if (autopower) { + if (!stby_layoff) { + if (pwm > max(20, (cur_t - 150) / 50 * round(25 - min(15, v))) + 5) { + //if (target_t-cur_t > 0.715*exp(0.0077*target_t)) { + //if (cur_t / (double)target_t < STANDBY_TEMPERATURE_DROP) { + if (autopower_repeat_under || stby) { + if (stby && !wasOff) { + setStandby(false); + } else { + last_temperature_drop = millis() / 1000; + } + } + autopower_repeat_under = true; + } else if (wasOff) { + wasOff = false; + } else { + autopower_repeat_under = false; //over the max pwm for at least two times + } + } + if (!off && !stby && millis() / 1000 > (last_temperature_drop + STANDBY_TIMEOUT)) { + setStandby(true); + } + if (!off && (stby || stby_layoff) && millis() / 1000 > (last_on_state + OFF_TIMEOUT)) { + setOff(true); + } + } +#endif + blink = !blink; + force_redraw = false; +} + +void compute(void) { +#ifndef USE_TFT_RESET + setStandbyLayoff(!digitalRead(STBY_NO)); //do not measure while heater is active, potential is not neccessary == GND +#endif + cur_t = getTemperature(); + if (off) { + target_t = 0; + if (cur_t < adc_offset + TEMP_RISE) { + threshold_counter = TEMP_UNDER_THRESHOLD; //reset counter + } + } else { + if (stby_layoff || stby) { + target_t = TEMP_STBY; + } else { + target_t = set_t; + } + if (cur_t - last_measured <= -30 && last_measured != 999) { + setError(EXCESSIVE_FALL); //decrease of more than 30 degree is uncommon, short of ring and gnd is possible. + } + if (cur_t < adc_offset + TEMP_RISE) { + if (threshold_counter == 0) { + setError(NOT_HEATING); //temperature is not reached in desired time, short of sensor and gnd too? + } else { + threshold_counter--; + } + } else { + threshold_counter = THRES_MAX_DECEED; //reset counter to a smaller value to allow small oscillation of temperature + } + } + + set_td = target_t; + cur_td = cur_t; + last_measured = cur_t; + + heaterPID.Compute(); + if (error != NO_ERROR || off) { + pwm = 0; + } else { + pwm = min(255, pid_val * 255); + } + analogWrite(HEATER_PWM, pwm); +} + +void timer_isr(void) { + if (cnt_compute >= TIME_COMPUTE_IN_MS) { + analogWrite(HEATER_PWM, 0); //switch off heater to let the low pass settle + + if (cnt_compute >= TIME_COMPUTE_IN_MS + DELAY_BEFORE_MEASURE) { + compute(); + cnt_compute = 0; + } + } + cnt_compute++; + + if (cnt_sw_poll >= TIME_SW_POLL_IN_MS) { + timer_sw_poll(); + cnt_sw_poll = 0; + } + cnt_sw_poll++; + + if (cnt_measure_voltage >= TIME_MEASURE_VOLTAGE_IN_MS) { + measureVoltage(); + cnt_measure_voltage = 0; + } + cnt_measure_voltage++; +} + +void setError(error_type e) { + error = e; + setOff(true); +} + +uint16_t serialReadTemp(void) { + uint16_t t; + uint8_t n; + n = Serial.read() - '0'; + t = min(9, max(0, n)) * 100; + n = Serial.read() - '0'; + t += min(9, max(0, n)) * 10; + n = Serial.read() - '0'; + t += min(9, max(0, n)) * 1; + return t; +} + +void loop(void) { + analogWrite(HEAT_LED, pwm); + //Switch to following if the oscillation of the led bothers you + //digitalWrite(HEAT_LED, cur_t+5 < target || (abs((int16_t)cur_t-(int16_t)target) <= 5 && (millis()/(stby?1000:500))%2)); + + if (sendNext <= millis()) { + sendNext += 100; +#ifndef TEST_ADC + Serial.print(stored[0]); + Serial.print(";"); + Serial.print(stored[1]); + Serial.print(";"); + Serial.print(stored[2]); + Serial.print(";"); + Serial.print(off ? 0 : 1); + Serial.print(";"); + Serial.print(error); + Serial.print(";"); + Serial.print(stby ? 1 : 0); + Serial.print(";"); + Serial.print(stby_layoff ? 1 : 0); + Serial.print(";"); + Serial.print(set_t); + Serial.print(";"); + Serial.print(cur_t); + Serial.print(";"); + Serial.print(pid_val); + Serial.print(";"); + Serial.print(v_c2 > 1.0 ? v_c1 : 0.0); + Serial.print(";"); + Serial.print(v_c2); + Serial.print(";"); + Serial.println(v); +#endif + Serial.flush(); + display(); + } + if (Serial.available()) { + uint16_t t = 0; + switch (Serial.read()) { + //Set new Temperature (eg. S350 to set to 350C) + case 'T': + if (Serial.available() >= 3) { + t = serialReadTemp(); + //Serial.println(t); + if (t <= TEMP_MAX && t >= TEMP_MIN) { + set_t = t; + updateEEPROM(); + } + } + break; + //Store new Preset (eg. P1200 to store 200C to Preset 1, NOT 0 indexed) + case 'P': + if (Serial.available() >= 4) { + uint8_t slot = Serial.read() - '1'; + if (slot < 3) { + t = serialReadTemp(); + if (t <= TEMP_MAX && t >= TEMP_MIN) { + stored[slot] = t; + updateEEPROM(); + } + } + } + break; + //Clear errors + case 'C': + error = NO_ERROR; + break; + //Set standby + case 'S': + setStandby(Serial.read() == '1'); + break; + //Set on/off + case 'O': + setOff(Serial.read() == '0'); + break; + } + } + delay(DELAY_MAIN_LOOP); + if (power_down) { + powerDown(); + } +} diff --git a/TFT_ILI9163C.cpp b/TFT_ILI9163C.cpp new file mode 100644 index 0000000..cbad3bf --- /dev/null +++ b/TFT_ILI9163C.cpp @@ -0,0 +1,1114 @@ +#include "TFT_ILI9163C.h" +#include +#include "pins_arduino.h" +#include "wiring_private.h" +#include + +#if defined(SPI_HAS_TRANSACTION) + static SPISettings ILI9163C_SPI; +#endif + + +//constructors + +#if defined(__MK20DX128__) || defined(__MK20DX256__) + TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin,uint8_t mosi,uint8_t sclk) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT) + { + _cs = cspin; + _rs = dcpin; + _rst = rstpin; + _mosi = mosi; + _sclk = sclk; + } +#elif defined(__MKL26Z64__) + TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin,uint8_t mosi,uint8_t sclk) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT) + { + _cs = cspin; + _rs = dcpin; + _rst = rstpin; + _mosi = mosi; + _sclk = sclk; + _useSPI1 = false; + if ((_mosi == 0 || _mosi == 21) && (_sclk == 20)) _useSPI1 = true; + } +#else + TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT) + { + _cs = cspin; + _rs = dcpin; + _rst = rstpin; + } +#endif + + +//Arduino Uno, Leonardo, Mega, Teensy 2.0, etc +#if defined(__AVR__) + + inline void TFT_ILI9163C::spiwrite(uint8_t c) + { + SPDR = c; + while(!(SPSR & _BV(SPIF))); + } + + void TFT_ILI9163C::writecommand(uint8_t c) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + *rsport &= ~rspinmask;//low + *csport &= ~cspinmask;//low + spiwrite(c); + *csport |= cspinmask;//hi + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + void TFT_ILI9163C::writedata(uint8_t c) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + *rsport |= rspinmask;//hi + *csport &= ~cspinmask;//low + spiwrite(c); + *csport |= cspinmask;//hi + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + void TFT_ILI9163C::writedata16(uint16_t d) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + *rsport |= rspinmask;//hi + *csport &= ~cspinmask;//low + spiwrite(d >> 8); + spiwrite(d); + *csport |= cspinmask;//hi + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + void TFT_ILI9163C::setBitrate(uint32_t n) + { + #if !defined (SPI_HAS_TRANSACTION) + if (n >= 8000000) { + SPI.setClockDivider(SPI_CLOCK_DIV2); + } else if (n >= 4000000) { + SPI.setClockDivider(SPI_CLOCK_DIV4); + } else if (n >= 2000000) { + SPI.setClockDivider(SPI_CLOCK_DIV8); + } else { + SPI.setClockDivider(SPI_CLOCK_DIV16); + } + #endif + } +#elif defined(__SAM3X8E__)// Arduino Due + inline void TFT_ILI9163C::spiwrite(uint8_t c) + { + SPI.transfer(c); + } + + void TFT_ILI9163C::writecommand(uint8_t c) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + rsport->PIO_CODR |= rspinmask;//LO + csport->PIO_CODR |= cspinmask;//LO + spiwrite(c); + csport->PIO_SODR |= cspinmask;//HI + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + void TFT_ILI9163C::writedata(uint8_t c) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + rsport->PIO_SODR |= rspinmask;//HI + csport->PIO_CODR |= cspinmask;//LO + spiwrite(c); + csport->PIO_SODR |= cspinmask;//HI + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + void TFT_ILI9163C::writedata16(uint16_t d) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + rsport->PIO_SODR |= rspinmask;//HI + csport->PIO_CODR |= cspinmask;//LO + spiwrite(d >> 8); + spiwrite(d); + csport->PIO_SODR |= cspinmask;//HI + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + + void TFT_ILI9163C::setBitrate(uint32_t n) + { + #if !defined(SPI_HAS_TRANSACTION) + uint32_t divider = 1; + while (divider < 255) { + if (n >= 84000000 / divider) break; + divider = divider - 1; + } + SPI.setClockDivider(divider); + #endif + } +#elif defined(__MKL26Z64__)//Teensy LC (preliminary + + void TFT_ILI9163C::writecommand(uint8_t c) + { + if (_useSPI1){ + SPI1.beginTransaction(ILI9163C_SPI); + digitalWriteFast(_rs,LOW); + digitalWriteFast(_cs,LOW); + SPI1.transfer(c); + digitalWriteFast(_cs,HIGH); + SPI1.endTransaction(); + } else { + SPI.beginTransaction(ILI9163C_SPI); + digitalWriteFast(_rs,LOW); + digitalWriteFast(_cs,LOW); + SPI.transfer(c); + digitalWriteFast(_cs,HIGH); + SPI.endTransaction(); + } + } + + void TFT_ILI9163C::writedata(uint8_t c) + { + if (_useSPI1){ + SPI1.beginTransaction(ILI9163C_SPI); + digitalWriteFast(_rs,HIGH); + digitalWriteFast(_cs,LOW); + SPI1.transfer(c); + digitalWriteFast(_cs,HIGH); + SPI1.endTransaction(); + } else { + SPI.beginTransaction(ILI9163C_SPI); + digitalWriteFast(_rs,HIGH); + digitalWriteFast(_cs,LOW); + SPI.transfer(c); + digitalWriteFast(_cs,HIGH); + SPI.endTransaction(); + } + } + + void TFT_ILI9163C::writedata16(uint16_t d) + { + if (_useSPI1){ + SPI1.beginTransaction(ILI9163C_SPI); + digitalWriteFast(_rs,HIGH); + digitalWriteFast(_cs,LOW); + SPI1.transfer16(d); + digitalWriteFast(_cs,HIGH); + SPI1.endTransaction(); + } else { + SPI.beginTransaction(ILI9163C_SPI); + digitalWriteFast(_rs,HIGH); + digitalWriteFast(_cs,LOW); + SPI.transfer16(d); + digitalWriteFast(_cs,HIGH); + SPI.endTransaction(); + } + } + + void TFT_ILI9163C::setBitrate(uint32_t n) + { + //nop + } +#elif defined(__MK20DX128__) || defined(__MK20DX256__)//Teensy 3.0 & 3.1 + + void TFT_ILI9163C::setBitrate(uint32_t n) + { + //nop + } +#else + + void TFT_ILI9163C::writecommand(uint8_t c) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + digitalWrite(_rs,LOW); + digitalWrite(_cs,LOW); + SPI.transfer(c); + digitalWrite(_cs,HIGH); + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + void TFT_ILI9163C::writedata(uint8_t c) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + digitalWrite(_rs,HIGH); + digitalWrite(_cs,LOW); + SPI.transfer(c); + digitalWrite(_cs,HIGH); + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + void TFT_ILI9163C::writedata16(uint16_t d) + { + #if defined(SPI_HAS_TRANSACTION) + SPI.beginTransaction(ILI9163C_SPI); + #endif + digitalWrite(_rs,HIGH); + digitalWrite(_cs,LOW); + SPI.transfer(d >> 8); + SPI.transfer(d); + digitalWrite(_cs,HIGH); + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif + } + + void TFT_ILI9163C::setBitrate(uint32_t n) + { + //nop + } +#endif //#if defined(TEENSY3.x) + + +void TFT_ILI9163C::begin(void) +{ + sleep = 0; + _initError = 0b00000000; +#if defined(__AVR__) + pinMode(_rs, OUTPUT); + pinMode(_cs, OUTPUT); + csport = portOutputRegister(digitalPinToPort(_cs)); + rsport = portOutputRegister(digitalPinToPort(_rs)); + cspinmask = digitalPinToBitMask(_cs); + rspinmask = digitalPinToBitMask(_rs); + SPI.begin(); + #if !defined(SPI_HAS_TRANSACTION) + SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + #else + ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0); + #endif + *csport &= ~cspinmask;// toggle CS low so it'll listen to us +#elif defined(__SAM3X8E__) + pinMode(_rs, OUTPUT); + pinMode(_cs, OUTPUT); + csport = digitalPinToPort(_cs); + rsport = digitalPinToPort(_rs); + cspinmask = digitalPinToBitMask(_cs); + rspinmask = digitalPinToBitMask(_rs); + SPI.begin(); + #if !defined(SPI_HAS_TRANSACTION) + SPI.setClockDivider(5); // 8 MHz + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + #else + ILI9163C_SPI = SPISettings(24000000, MSBFIRST, SPI_MODE0); + #endif + csport ->PIO_CODR |= cspinmask; // toggle CS low so it'll listen to us +#elif defined(__MKL26Z64__)//Teensy LC (preliminary) + pinMode(_rs, OUTPUT); + pinMode(_cs, OUTPUT); + if (_useSPI1){ + if ((_mosi == 0 || _mosi == 21) && (_sclk == 20)) {//identify alternate SPI channel 1 (24Mhz) + ILI9163C_SPI = SPISettings(24000000, MSBFIRST, SPI_MODE0); + SPI1.setMOSI(_mosi); + SPI1.setSCK(_sclk); + SPI1.begin(); + _useSPI1 = true; //confirm + } else { + bitSet(_initError,0); + return; + } + if (!SPI.pinIsChipSelect(_cs)) {//ERROR + bitSet(_initError,1); + return; + } + } else { + if ((_mosi == 11 || _mosi == 7) && (_sclk == 13 || _sclk == 14)) {//valid SPI pins? + ILI9163C_SPI = SPISettings(12000000, MSBFIRST, SPI_MODE0); + SPI.setMOSI(_mosi); + SPI.setSCK(_sclk); + SPI.begin(); + _useSPI1 = false; //confirm + } else { + bitSet(_initError,0); + return; + } + if (!SPI.pinIsChipSelect(_cs)) {//ERROR + bitSet(_initError,1); + return; + } + } + digitalWriteFast(_cs, LOW); +#elif defined(__MK20DX128__) || defined(__MK20DX256__) + ILI9163C_SPI = SPISettings(30000000, MSBFIRST, SPI_MODE0); + if ((_mosi == 11 || _mosi == 7) && (_sclk == 13 || _sclk == 14)) { + SPI.setMOSI(_mosi); + SPI.setSCK(_sclk); + } else { + bitSet(_initError,0); + return; + } + SPI.begin(); + if (SPI.pinIsChipSelect(_cs, _rs)) { + pcs_data = SPI.setCS(_cs); + pcs_command = pcs_data | SPI.setCS(_rs); + } else { + pcs_data = 0; + pcs_command = 0; + bitSet(_initError,1); + return; + } +#else//all the rest of possible boards + pinMode(_rs, OUTPUT); + pinMode(_cs, OUTPUT); + SPI.begin(); + #if !defined(SPI_HAS_TRANSACTION) + SPI.setClockDivider(4); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + #else + ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0); + #endif + digitalWrite(_cs, LOW); +#endif + if (_rst != 255) { + pinMode(_rst, OUTPUT); + digitalWrite(_rst, HIGH); + delay(500); + digitalWrite(_rst, LOW); + delay(500); + digitalWrite(_rst, HIGH); + delay(500); + } + +/* +7) MY: 1(bottom to top), 0(top to bottom) Row Address Order +6) MX: 1(R to L), 0(L to R) Column Address Order +5) MV: 1(Exchanged), 0(normal) Row/Column exchange +4) ML: 1(bottom to top), 0(top to bottom) Vertical Refresh Order +3) RGB: 1(BGR), 0(RGB) Color Space +2) MH: 1(R to L), 0(L to R) Horizontal Refresh Order +1) +0) + + MY, MX, MV, ML,RGB, MH, D1, D0 + 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //normal + 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //Y-Mirror + 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Mirror + 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Y-Mirror + 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange + 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange, Y-Mirror + 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 //XY exchange + 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 +*/ + _Mactrl_Data = 0b00000000; + _colorspaceData = __COLORSPC;//start with default data; + chipInit(); +} + +uint8_t TFT_ILI9163C::errorCode(void) +{ + return _initError; +} + +void TFT_ILI9163C::chipInit() { + uint8_t i; + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + + writecommand_cont(CMD_SWRESET);//software reset + delay(500); + + writecommand_cont(CMD_SLPOUT);//exit sleep + delay(5); + + writecommand_cont(CMD_PIXFMT);//Set Color Format 16bit + writedata8_cont(0x05); + delay(5); + + writecommand_cont(CMD_GAMMASET);//default gamma curve 3 + writedata8_cont(0x08);//0x04 + delay(1); + + writecommand_cont(CMD_GAMRSEL);//Enable Gamma adj + writedata8_cont(0x01); + delay(1); + + writecommand_cont(CMD_NORML); + + writecommand_cont(CMD_DFUNCTR); + writedata8_cont(0b11111111);// + writedata8_cont(0b00000110);// + + writecommand_cont(CMD_PGAMMAC);//Positive Gamma Correction Setting + for (i=0;i<15;i++){ + writedata8_cont(pGammaSet[i]); + } + + writecommand_cont(CMD_NGAMMAC);//Negative Gamma Correction Setting + for (i=0;i<15;i++){ + writedata8_cont(nGammaSet[i]); + } + + writecommand_cont(CMD_FRMCTR1);//Frame Rate Control (In normal mode/Full colors) + writedata8_cont(0x08);//0x0C//0x08 + writedata8_cont(0x02);//0x14//0x08 + delay(1); + + writecommand_cont(CMD_DINVCTR);//display inversion + writedata8_cont(0x07); + delay(1); + + writecommand_cont(CMD_PWCTR1);//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD + writedata8_cont(0x0A);//4.30 - 0x0A + writedata8_cont(0x02);//0x05 + delay(1); + + writecommand_cont(CMD_PWCTR2);//Set BT[2:0] for AVDD & VCL & VGH & VGL + writedata8_cont(0x02); + delay(1); + + writecommand_cont(CMD_VCOMCTR1);//Set VMH[6:0] & VML[6:0] for VOMH & VCOML + writedata8_cont(0x50);//0x50 + writedata8_cont(99);//0x5b + delay(1); + + writecommand_cont(CMD_VCOMOFFS); + writedata8_cont(0);//0x40 + delay(1); + + writecommand_cont(CMD_CLMADRS);//Set Column Address + writedata16_cont(0x00); + writedata16_cont(_GRAMWIDTH); + + writecommand_cont(CMD_PGEADRS);//Set Page Address + writedata16_cont(0x00); + writedata16_cont(_GRAMHEIGH); + // set scroll area (thanks Masuda) + writecommand_cont(CMD_VSCLLDEF); + writedata16_cont(__OFFSET); + writedata16_cont(_GRAMHEIGH - __OFFSET); + writedata16_last(0); + + SPI.endTransaction(); + + colorSpace(_colorspaceData); + + setRotation(0); + + SPI.beginTransaction(ILI9163C_SPI); + + writecommand_cont(CMD_DISPON);//display ON + delay(1); + writecommand_last(CMD_RAMWR);//Memory Write + + SPI.endTransaction(); + delay(1); + #else + writecommand(CMD_SWRESET);//software reset + delay(500); + + writecommand(CMD_SLPOUT);//exit sleep + delay(5); + + writecommand(CMD_PIXFMT);//Set Color Format 16bit + writedata(0x05); + delay(5); + + writecommand(CMD_GAMMASET);//default gamma curve 3 + writedata(0x04);//0x04 + delay(1); + + writecommand(CMD_GAMRSEL);//Enable Gamma adj + writedata(0x01); + delay(1); + + writecommand(CMD_NORML); + + writecommand(CMD_DFUNCTR); + writedata(0b11111111);// + writedata(0b00000110);// + + writecommand(CMD_PGAMMAC);//Positive Gamma Correction Setting + for (i=0;i<15;i++){ + writedata(pGammaSet[i]); + } + + writecommand(CMD_NGAMMAC);//Negative Gamma Correction Setting + for (i=0;i<15;i++){ + writedata(nGammaSet[i]); + } + + writecommand(CMD_FRMCTR1);//Frame Rate Control (In normal mode/Full colors) + writedata(0x08);//0x0C//0x08 + writedata(0x02);//0x14//0x08 + delay(1); + + writecommand(CMD_DINVCTR);//display inversion + writedata(0x07); + delay(1); + + writecommand(CMD_PWCTR1);//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD + writedata(0x0A);//4.30 - 0x0A + writedata(0x02);//0x05 + delay(1); + + writecommand(CMD_PWCTR2);//Set BT[2:0] for AVDD & VCL & VGH & VGL + writedata(0x02); + delay(1); + + writecommand(CMD_VCOMCTR1);//Set VMH[6:0] & VML[6:0] for VOMH & VCOML + writedata(0x50);//0x50 + writedata(99);//0x5b + delay(1); + + writecommand(CMD_VCOMOFFS); + writedata(0);//0x40 + delay(1); + + writecommand(CMD_CLMADRS);//Set Column Address + writedata16(0x00); + writedata16(_GRAMWIDTH); + + writecommand(CMD_PGEADRS);//Set Page Address + writedata16(0X00); + writedata16(_GRAMHEIGH); + // set scroll area (thanks Masuda) + writecommand(CMD_VSCLLDEF); + writedata16(__OFFSET); + writedata16(_GRAMHEIGH - __OFFSET); + writedata16(0); + + colorSpace(_colorspaceData); + + setRotation(0); + writecommand(CMD_DISPON);//display ON + delay(1); + writecommand(CMD_RAMWR);//Memory Write + + delay(1); + #endif + fillScreen(BLACK); +} + +/* +Colorspace selection: +0: RGB +1: GBR +*/ +void TFT_ILI9163C::colorSpace(uint8_t cspace) { + if (cspace < 1){ + bitClear(_Mactrl_Data,3); + } else { + bitSet(_Mactrl_Data,3); + } +} + +void TFT_ILI9163C::invertDisplay(boolean i) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_last(i ? CMD_DINVON : CMD_DINVOF); + SPI.endTransaction(); + #else + writecommand(i ? CMD_DINVON : CMD_DINVOF); + #endif +} + +void TFT_ILI9163C::display(boolean onOff) { + if (onOff){ + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_last(CMD_DISPON); + SPI.endTransaction(); + #else + writecommand(CMD_DISPON); + #endif + } else { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_last(CMD_DISPOFF); + SPI.endTransaction(); + #else + writecommand(CMD_DISPOFF); + #endif + } +} + +void TFT_ILI9163C::idleMode(boolean onOff) { + if (onOff){ + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_last(CMD_IDLEON); + SPI.endTransaction(); + #else + writecommand(CMD_IDLEON); + #endif + } else { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_last(CMD_IDLEOF); + SPI.endTransaction(); + #else + writecommand(CMD_IDLEOF); + #endif + } +} + +void TFT_ILI9163C::sleepMode(boolean mode) { + if (mode){ + if (sleep == 1) return;//already sleeping + sleep = 1; + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_last(CMD_SLPIN); + SPI.endTransaction(); + #else + writecommand(CMD_SLPIN); + #endif + delay(5);//needed + } else { + if (sleep == 0) return; //Already awake + sleep = 0; + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_last(CMD_SLPOUT); + SPI.endTransaction(); + #else + writecommand(CMD_SLPOUT); + #endif + delay(120);//needed + } +} + +void TFT_ILI9163C::defineScrollArea(uint16_t tfa, uint16_t bfa){ + tfa += __OFFSET; + int16_t vsa = _GRAMHEIGH - tfa - bfa; + if (vsa >= 0) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_cont(CMD_VSCLLDEF); + writedata16_cont(tfa); + writedata16_cont(vsa); + writedata16_last(bfa); + SPI.endTransaction(); + #else + writecommand(CMD_VSCLLDEF); + writedata16(tfa); + writedata16(vsa); + writedata16(bfa); + #endif + } +} + +void TFT_ILI9163C::scroll(uint16_t adrs) { + if (adrs <= _GRAMHEIGH) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_cont(CMD_VSSTADRS); + writedata16_last(adrs + __OFFSET); + SPI.endTransaction(); + #else + writecommand(CMD_VSSTADRS); + writedata16(adrs + __OFFSET); + #endif + } +} + + +//corrected! v3 +void TFT_ILI9163C::clearScreen(uint16_t color) { + int px; + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + _setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH); + for (px = 0;px < _GRAMSIZE; px++){ + writedata16_cont(color); + } + writecommand_last(CMD_NOP); + SPI.endTransaction(); + #else + setAddr(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//go home + for (px = 0;px < _GRAMSIZE; px++){ + writedata16(color); + } + #endif +} + +void TFT_ILI9163C::startPushData(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { + setAddr(x0,y0,x1,y1); +} + +void TFT_ILI9163C::pushData(uint16_t color) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + writedata16_cont(color); + #else + writedata16(color); + #endif +} + + +void TFT_ILI9163C::endPushData() { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + writecommand_last(CMD_NOP); + SPI.endTransaction(); + #endif +} + + +void TFT_ILI9163C::pushColor(uint16_t color) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writedata16_last(color); + SPI.endTransaction(); + #else + writedata16(color); + #endif +} + +void TFT_ILI9163C::writeScreen24(const uint32_t *bitmap,uint16_t size) { + uint16_t color; + uint16_t px; + #if defined(__MK20DX128__) || defined(__MK20DX256__) + writecommand_cont(CMD_RAMWR); + for (px = 0;px < size; px++){//16384 + color = Color24To565(bitmap[px]); + writedata16_cont(color); + } + _setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//home + SPI.endTransaction(); + #else + writecommand(CMD_RAMWR); + for (px = 0;px < size; px++){ + color = Color24To565(bitmap[px]); + writedata16(color); + } + homeAddress(); + #endif +} + +void TFT_ILI9163C::homeAddress() { + setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH); +} + + + +void TFT_ILI9163C::setCursor(int16_t x, int16_t y) { + if (boundaryCheck(x,y)) return; + setAddrWindow(0x00,0x00,x,y); + cursor_x = x; + cursor_y = y; +} + + + + + +void TFT_ILI9163C::drawPixel(int16_t x, int16_t y, uint16_t color) { + if (boundaryCheck(x,y)) return; + if ((x < 0) || (y < 0)) return; + setAddr(x,y,x+1,y+1); + #if defined(__MK20DX128__) || defined(__MK20DX256__) + writedata16_last(color); + SPI.endTransaction(); + #else + writedata16(color); + #endif +} + + + +void TFT_ILI9163C::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { + // Rudimentary clipping + if (boundaryCheck(x,y)) return; + if (((y + h) - 1) >= _height) h = _height-y; + setAddr(x,y,x,(y+h)-1); + while (h-- > 0) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + if (h == 0){ + writedata16_last(color); + } else { + writedata16_cont(color); + } + #else + writedata16(color); + #endif + } + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif +} + +bool TFT_ILI9163C::boundaryCheck(int16_t x,int16_t y){ + if ((x >= _width) || (y >= _height)) return true; + return false; +} + +void TFT_ILI9163C::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { + // Rudimentary clipping + if (boundaryCheck(x,y)) return; + if (((x+w) - 1) >= _width) w = _width-x; + setAddr(x,y,(x+w)-1,y); + while (w-- > 0) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + if (w == 0){ + writedata16_last(color); + } else { + writedata16_cont(color); + } + #else + writedata16(color); + #endif + } + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif +} + +void TFT_ILI9163C::fillScreen(uint16_t color) { + clearScreen(color); +} + +// fill a rectangle +void TFT_ILI9163C::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { + if (boundaryCheck(x,y)) return; + if (((x + w) - 1) >= _width) w = _width - x; + if (((y + h) - 1) >= _height) h = _height - y; + setAddr(x,y,(x+w)-1,(y+h)-1); + for (y = h;y > 0;y--) { + for (x = w;x > 1;x--) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + writedata16_cont(color); + #else + writedata16(color); + #endif + } + #if defined(__MK20DX128__) || defined(__MK20DX256__) + writedata16_last(color); + #else + writedata16(color); + #endif + } + #if defined(SPI_HAS_TRANSACTION) + SPI.endTransaction(); + #endif +} + +#if defined(__MK20DX128__) || defined(__MK20DX256__) +void TFT_ILI9163C::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color){ + if (y0 == y1) { + if (x1 > x0) { + drawFastHLine(x0, y0, x1 - x0 + 1, color); + } else if (x1 < x0) { + drawFastHLine(x1, y0, x0 - x1 + 1, color); + } else { + drawPixel(x0, y0, color); + } + return; + } else if (x0 == x1) { + if (y1 > y0) { + drawFastVLine(x0, y0, y1 - y0 + 1, color); + } else { + drawFastVLine(x0, y1, y0 - y1 + 1, color); + } + return; + } + + bool steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { + swap(x0, y0); + swap(x1, y1); + } + if (x0 > x1) { + swap(x0, x1); + swap(y0, y1); + } + + int16_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int16_t err = dx / 2; + int16_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1; + } + + SPI.beginTransaction(ILI9163C_SPI); + + int16_t xbegin = x0; + if (steep) { + for (; x0<=x1; x0++) { + err -= dy; + if (err < 0) { + int16_t len = x0 - xbegin; + if (len) { + VLine(y0, xbegin, len + 1, color); + } else { + Pixel(y0, x0, color); + } + xbegin = x0 + 1; + y0 += ystep; + err += dx; + } + } + if (x0 > xbegin + 1) { + VLine(y0, xbegin, x0 - xbegin, color); + } + + } else { + for (; x0<=x1; x0++) { + err -= dy; + if (err < 0) { + int16_t len = x0 - xbegin; + if (len) { + HLine(xbegin, y0, len + 1, color); + } else { + Pixel(x0, y0, color); + } + xbegin = x0 + 1; + y0 += ystep; + err += dx; + } + } + if (x0 > xbegin + 1) { + HLine(xbegin, y0, x0 - xbegin, color); + } + } + writecommand_last(CMD_NOP); + SPI.endTransaction(); +} + +void TFT_ILI9163C::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){ + SPI.beginTransaction(ILI9163C_SPI); + HLine(x, y, w, color); + HLine(x, y+h-1, w, color); + VLine(x, y, h, color); + VLine(x+w-1, y, h, color); + writecommand_last(CMD_NOP); + SPI.endTransaction(); +} + + +#endif + +void TFT_ILI9163C::setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){ + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + _setAddrWindow(x0,y0,x1,y1); + #else + setAddrWindow(x0,y0,x1,y1); + #endif +} + +void TFT_ILI9163C::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + _setAddrWindow(x0,y0,x1,y1); + SPI.endTransaction(); + #else + writecommand(CMD_CLMADRS); // Column + if (rotation == 0 || rotation > 1){ + writedata16(x0); + writedata16(x1); + } else { + writedata16(x0 + __OFFSET); + writedata16(x1 + __OFFSET); + } + + writecommand(CMD_PGEADRS); // Page + if (rotation == 0){ + writedata16(y0 + __OFFSET); + writedata16(y1 + __OFFSET); + } else { + writedata16(y0); + writedata16(y1); + } + writecommand(CMD_RAMWR); //Into RAM + #endif +} + +#if defined(__MK20DX128__) || defined(__MK20DX256__) +void TFT_ILI9163C::_setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { + writecommand_cont(CMD_CLMADRS); // Column + if (rotation == 0 || rotation > 1){ + writedata16_cont(x0); + writedata16_cont(x1); + } else { + writedata16_cont(x0 + __OFFSET); + writedata16_cont(x1 + __OFFSET); + } + writecommand_cont(CMD_PGEADRS); // Page + if (rotation == 0){ + writedata16_cont(y0 + __OFFSET); + writedata16_cont(y1 + __OFFSET); + } else { + writedata16_cont(y0); + writedata16_cont(y1); + } + writecommand_cont(CMD_RAMWR); //Into RAM +} +#endif + +void TFT_ILI9163C::setRotation(uint8_t m) { + rotation = m % 4; // can't be higher than 3 + switch (rotation) { + case 0: + _Mactrl_Data = 0b00001000; + _width = _TFTWIDTH; + _height = _TFTHEIGHT;//-__OFFSET; + break; + case 1: + _Mactrl_Data = 0b01101000; + _width = _TFTHEIGHT;//-__OFFSET; + _height = _TFTWIDTH; + break; + case 2: + _Mactrl_Data = 0b11001000; + _width = _TFTWIDTH; + _height = _TFTHEIGHT;//-__OFFSET; + break; + case 3: + _Mactrl_Data = 0b10101000; + _width = _TFTWIDTH; + _height = _TFTHEIGHT;//-__OFFSET; + break; + } + colorSpace(_colorspaceData); + #if defined(__MK20DX128__) || defined(__MK20DX256__) + SPI.beginTransaction(ILI9163C_SPI); + writecommand_cont(CMD_MADCTL); + writedata8_last(_Mactrl_Data); + SPI.endTransaction(); + #else + writecommand(CMD_MADCTL); + writedata(_Mactrl_Data); + #endif +} + + + + diff --git a/definitions.h b/definitions.h new file mode 100644 index 0000000..745e438 --- /dev/null +++ b/definitions.h @@ -0,0 +1,195 @@ +#define VERSION "3.1" +#define EE_VERSION 31 +#define EEPROM_CHECK 42 + +#define BAR_HEIGHT 4 //Should be no bigger than 5 + +/* + TIPS ARE SPECIFIED FOR 450 DEGREE MAX + If read 1023 on Analog in, the tip is turned off automatically +*/ +#define TEMP_MAX 450 +#define TEMP_MIN 200 +#define TEMP_STBY 150 +#define TEMP_COLD 50// (adc_offset + 15) + +#define SHUTOFF_ACTIVE +#define BOOTHEAT_ACTIVE + +#define STANDBY_TIMEOUT 240 // seconds without any significant temperature drop, if exceeded it will standby +#define OFF_TIMEOUT 900 // seconds in standby before turning off + +#define TEMP_RISE 0.1 //threshold temperature, that must be exceeded delta in given time: +#define TEMP_UNDER_THRESHOLD 30 // x (TIME_COMPUTE_IN_MS + DELAY_BEFORE_MEASURE) +#define THRES_MAX_DECEED 5 //max times the threshold temperature may be undercut by the current temperature + +//Temperature in degree to rise at least in given time +#define TEMP_MIN_RISE 1 +//Time in that the temperature must rise by the set temperature +#define TEMP_RISE_TIME 5000 // increase from 1000ms to 5000ms to enshure proper heating + +//#define OLD_PWM + +// RX 0 +// TX 1 +#define SW_STBY 2 +#define HEATER_PWM 3 +#define SW_DOWN 4 +#define HEAT_LED 5 +#define SW_UP 6 +#define SW_T3 7 +#define SW_T2 8 +#define SW_T1 9 +#define TFT_CS 10 // Display Pin: 7 CS +// MOSI 11 // Display Pin: 4 SDA +#define POWER 12 //use MISO PULLUP as switch +// SCK 13 // Display Pin: 3 SCK +#define TEMP_SENSE A0 +#define STBY_NO A1 // Display Pin: 5 RES +#define BAT_C3 A2 +#define BAT_C2 A3 +#define BAT_C1 A4 +#define TFT_DC A5 // Display Pin: 6 RS +#ifdef PIN_A7 +#define CHARGEDET A6 +#define VIN A7 +#endif + +#define kp 0.03 +#define ki 0.00001 +#define kd 0.0 + +#define TIME_COMPUTE_IN_MS 10 +#define TIME_MEASURE_VOLTAGE_IN_MS 200 +#define TIME_SW_POLL_IN_MS 10 +#define DELAY_BEFORE_MEASURE 10 +#define DELAY_MAIN_LOOP 10 +#define PID_SAMPLE_TIME 10 + +#define ADC_TO_TEMP_GAIN 0.54 //default value if no calibration is performed +#define ADC_TO_TEMP_OFFSET 42.8 //default value if no calibration is performed + +#define EEPROM_SET_T 8 +#define EEPROM_VERSION 10 +#define EEPROM_DISPLAY 11 +#define EEPROM_OPTIONS 12 +#define EEPROM_REVISION 13 +#define EEPROM_ADCTTG 14 +#define EEPROM_ADCOFF (EEPROM_ADCTTG + sizeof(float)) + +#define EEPROM_INSTALL 42 +#define REF_T1 275 +#define REF_T2 410 +#define DELTA_REF_T (REF_T2 - REF_T1) + + +typedef enum POWER_SOURCE { + NO_INIT, + POWER_USB, + POWER_CORD, + POWER_LIPO, + POWER_CHARGING +} p_source; +typedef enum ERROR_TYPE { + NO_ERROR, + EXCESSIVE_FALL, + NOT_HEATING, + NO_TIP, + BATTERY_LOW, + USB_ONLY +} error_type; + +const unsigned char power_cord [] PROGMEM = { + 0x00, 0x00, 0xC0, + 0x00, 0xFF, 0xC0, + 0x01, 0xFF, 0xDF, + 0x03, 0xFF, 0xDF, + 0xFB, 0xFF, 0xC0, + 0x03, 0xFF, 0xDF, + 0x01, 0xFF, 0xDF, + 0x00, 0xFF, 0xC0, + 0x00, 0x00, 0xC0 +}; + +const unsigned char maiskolben [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xe0, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xcf, 0xff, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xdc, 0xf7, + 0x18, 0x47, 0x89, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x26, 0x78, 0xc6, 0x33, 0x9c, 0x7f, 0x0c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x08, 0x23, 0x49, 0xe6, 0x1b, 0xff, 0xf8, 0x39, 0xd0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xc5, 0x31, 0xcf, 0xe7, 0x3f, 0xfe, 0x14, 0x21, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x47, 0xf9, 0xff, 0xff, 0xcc, + 0x40, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x4e, + 0x0f, 0xc1, 0x08, 0x04, 0x63, 0x00, 0x21, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x47, 0xe0, 0x0c, 0x01, 0x08, 0x07, 0xaf, 0x80, 0x60, 0x84, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x02, 0x0c, 0x01, 0x8c, 0xc7, 0xa4, 0x80, 0xe0, 0xf4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x0c, 0x60, 0x9f, 0xc7, + 0xf0, 0xf3, 0x33, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x83, + 0x0e, 0xe0, 0x77, 0x69, 0x9a, 0xf7, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0xfd, 0xb7, 0xb6, 0x67, 0x79, 0x9f, 0xfe, 0xee, 0x12, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xfc, 0xf3, 0xbe, 0xff, 0xfb, 0xff, 0xf8, 0x46, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcd, 0xcf, 0xbc, 0x63, 0x18, 0x6e, + 0x21, 0x80, 0x42, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8c, 0xfe, + 0x08, 0x42, 0x08, 0x44, 0x21, 0x48, 0x42, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x84, 0xe2, 0x1e, 0x4a, 0x18, 0x44, 0xe1, 0xc0, 0x63, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x63, 0x3c, 0x7b, 0x18, 0x6e, 0x60, 0x80, 0x31, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0xec, 0x71, 0x08, 0x22, + 0x10, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x39, + 0x84, 0x21, 0x8c, 0x33, 0x10, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x38, 0x84, 0x00, 0x08, 0x32, 0x10, 0x02, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x58, 0x10, 0x84, 0x00, 0x08, 0x20, 0x10, 0x03, 0xf1, 0x9f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x70, 0x44, 0x60, 0x08, 0x23, + 0x30, 0xc4, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, + 0xc7, 0x1f, 0xff, 0xff, 0x1f, 0x84, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0xc0, 0x7f, 0x82, 0x10, 0x8c, 0x03, 0x08, 0x84, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x78, 0x82, 0x10, 0x88, 0x01, 0x08, 0x84, 0x10, 0x87, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7c, 0x28, 0x82, 0x18, 0xc8, 0x21, + 0x08, 0x82, 0x10, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x28, + 0x42, 0x08, 0xc0, 0x21, 0x8c, 0x42, 0x10, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x00, + 0x00, 0x3f, 0xfc, 0x18, 0x42, 0x08, 0xc4, 0x11, 0x8c, 0x42, 0x10, 0x83, 0x80, 0x00, 0x00, 0x00, + 0x7f, 0xff, 0xfe, 0x89, 0xfc, 0xff, 0x94, 0x0c, 0x42, 0x08, 0x44, 0x30, 0x88, 0x42, 0x10, 0x03, + 0x18, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x0c, 0x62, 0x00, 0x04, 0x00, + 0x88, 0x42, 0x10, 0x03, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x04, 0x1c, + 0x20, 0x00, 0x88, 0x00, 0x88, 0x42, 0x10, 0xc7, 0x06, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x80, 0x1c, 0x23, 0x10, 0xc8, 0x00, 0x8c, 0x43, 0x30, 0xf9, 0x01, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x37, 0x9d, 0xbc, 0x30, 0xfe, 0xe7, 0x6f, 0x11, + 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0x04, 0x4c, 0xe7, 0x9e, 0x2f, + 0x31, 0x8e, 0x64, 0x31, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xce, 0x23, + 0x8f, 0xe7, 0x1d, 0xc7, 0x31, 0x8c, 0x64, 0x11, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x46, 0x30, 0xcf, 0xf6, 0x1c, 0xe6, 0x39, 0xcc, 0x64, 0x11, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x44, 0x38, 0xcc, 0x76, 0x18, 0xc2, 0x3d, 0x2c, 0x6c, 0x13, + 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x44, 0x38, 0xcc, 0x66, 0x10, 0x86, + 0x31, 0x08, 0x48, 0x13, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x44, 0x38, + 0xc0, 0x44, 0x10, 0x84, 0x21, 0x00, 0x48, 0x12, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x40, 0x30, 0x80, 0x44, 0x01, 0x04, 0x20, 0x00, 0x48, 0x1e, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x84, 0x44, 0x21, 0x04, 0x20, 0x0c, 0xfc, 0x26, + 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x86, 0xcc, 0x21, 0x04, + 0x23, 0x0f, 0x8e, 0xc2, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, + 0x8e, 0xff, 0xff, 0x0f, 0xfb, 0xf9, 0x84, 0x46, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x71, 0xf0, 0x6c, 0x31, 0xc4, 0x40, 0x19, 0x00, 0x46, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb8, 0x30, 0x4c, 0x21, 0x04, 0x40, 0x11, 0x00, 0x46, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x20, 0x48, 0x20, 0x00, + 0x02, 0x11, 0x08, 0x44, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x28, + 0x20, 0x08, 0x02, 0x00, 0x80, 0x11, 0x08, 0x4c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x22, 0x18, 0x20, 0x00, 0x02, 0x00, 0x80, 0x13, 0x1c, 0xd8, 0x00, 0x00, 0x03, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x18, 0x20, 0x00, 0x42, 0x08, 0x84, 0x1d, 0xe6, 0x38, + 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x18, 0x21, 0x1c, 0x7e, 0x0e, + 0x7f, 0x90, 0x44, 0x38, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7c, + 0x7c, 0xcc, 0x31, 0x88, 0x42, 0x10, 0x44, 0x38, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x42, 0x10, 0x08, 0x21, 0x08, 0x42, 0x10, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x40, 0x00, 0x08, 0x20, 0x08, 0x62, 0x10, 0x8c, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x08, + 0xc6, 0x21, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, + 0x60, 0x08, 0x44, 0x3f, 0xff, 0xe7, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..91d5974 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,21 @@ +TFT_ILI9163C KEYWORD1 +begin KEYWORD2 +setAddrWindow KEYWORD2 +pushColor KEYWORD2 +setBrightness KEYWORD2 +writeData KEYWORD2 +setBitrate KEYWORD2 +Color565 KEYWORD2 +setBitrate KEYWORD2 +clearScreen KEYWORD2 +Color24To565 KEYWORD2 +sleepMode KEYWORD2 +display KEYWORD2 +startPushData KEYWORD2 +pushData KEYWORD2 +endPushData KEYWORD2 +defineScrollArea KEYWORD2 +writeScreen24 KEYWORD2 +idleMode KEYWORD2 +errorCode KEYWORD2 + diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..0947fba --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=TFT_ILI9163C +version=0.9 +author=Max MC Costa +maintainer=sumotoy +sentence=A fast SPI driver for TFT drived by ILI9163C, fully SPI Transaction compatible and very fast with Teensy 3 +paragraph=This library works with many MCU's included Arduino's but it's particular fast with Teensy 3, Teensy 3.1. +category=Display +url=https://github.com/sumotoy/TFT_ILI9163C +architectures=*