├── Makefile ├── README.md └── main ├── app_main.c ├── commando.inc ├── component.mk ├── fonts.c ├── fonts.h ├── libcsid.h ├── libcsidlight.c ├── precalc.inc ├── ssd1306.c ├── ssd1306.h ├── xi2c.c └── xi2c.h /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | VERBOSE = 1 6 | PROJECT_NAME := esp32_sid 7 | include $(IDF_PATH)/make/project.mk 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cSID running on ESP32 with I2S 2 | 3 | Using a slightly modified [cSID-light](http://csdb.dk/release/?id=156587) by [Hermit](http://hermit.sidrip.com/) 4 | 5 | Based on the bundled I2S sample and [ESP32_OLED_webradio](https://github.com/kodera2t/ESP32_OLED_webradio) 6 | 7 | Running on a [ESP32 Audio development board](https://www.tindie.com/products/microwavemont/esp32-audio-developing-board-esp32-adb/) 8 | 9 | [![Video](https://img.youtube.com/vi/sQSfTh0OhkI/0.jpg)](https://www.youtube.com/watch?v=sQSfTh0OhkI) 10 | -------------------------------------------------------------------------------- /main/app_main.c: -------------------------------------------------------------------------------- 1 | /* Based on the ESP-IDF I2S Example */ 2 | #include "freertos/FreeRTOS.h" 3 | #include "freertos/task.h" 4 | #include "driver/i2s.h" 5 | #include "esp_system.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "xi2c.h" 13 | #include "fonts.h" 14 | #include "ssd1306.h" 15 | 16 | #include "commando.inc" 17 | 18 | // from ESP32 Audio shield demo 19 | 20 | static QueueHandle_t i2s_event_queue; 21 | 22 | #define I2C_EXAMPLE_MASTER_SCL_IO 14 /*!< gpio number for I2C master clock *///////////// 23 | #define I2C_EXAMPLE_MASTER_SDA_IO 13 /*!< gpio number for I2C master data *////////////// 24 | #define I2C_EXAMPLE_MASTER_NUM I2C_NUM_1 /*!< I2C port number for master dev */ 25 | #define I2C_EXAMPLE_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */ 26 | #define I2C_EXAMPLE_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */ 27 | #define I2C_EXAMPLE_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */ 28 | 29 | 30 | #define SAMPLE_RATE (22050) 31 | #define I2S_CHANNEL I2S_NUM_0 32 | // #define WAVE_FREQ_HZ (200) 33 | #define PI 3.14159265 34 | 35 | // #define SAMPLE_PER_CYCLE (SAMPLE_RATE / WAVE_FREQ_HZ) 36 | #define HALF_SAMPLERATE (SAMPLE_RATE / 2) 37 | 38 | unsigned long phase = 0; 39 | unsigned short waveform_buffer[128] = { 0, }; 40 | 41 | static void setup_triangle_sine_waves() 42 | { 43 | int samples = 300; 44 | unsigned short *mono_samples_data = (unsigned short *)malloc(2 * samples); 45 | unsigned short *samples_data = (unsigned short *)malloc(2 * 2 * samples); 46 | 47 | unsigned int i, sample_val; 48 | double sin_float; 49 | 50 | libcsid_render(mono_samples_data, samples); 51 | 52 | for(i = 0; i < samples; i ++) { 53 | sample_val = mono_samples_data[i]; 54 | samples_data[i * 2 + 0] = sample_val; 55 | 56 | if (i < 128) { 57 | waveform_buffer[i] = sample_val; 58 | } 59 | 60 | samples_data[i * 2 + 1] = sample_val; 61 | } 62 | 63 | int pos = 0; 64 | int left = 2 * 2 * samples; 65 | unsigned char *ptr = (unsigned char *)samples_data; 66 | 67 | while (left > 0) { 68 | int written = i2s_write_bytes(I2S_CHANNEL, (const char *)ptr, left, 100 / portTICK_RATE_MS); 69 | pos += written; 70 | ptr += written; 71 | left -= written; 72 | } 73 | 74 | free(samples_data); 75 | free(mono_samples_data); 76 | } 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | void audiorenderer_loop(void *pvParameter) { 88 | while(1) { 89 | setup_triangle_sine_waves(); 90 | } 91 | } 92 | 93 | void renderer_zero_dma_buffer() { 94 | i2s_zero_dma_buffer(I2S_CHANNEL); 95 | } 96 | 97 | void audioplayer_init() { 98 | i2s_mode_t mode = I2S_MODE_MASTER | I2S_MODE_TX; 99 | 100 | i2s_config_t i2s_config = { 101 | .mode = mode, // Only TX 102 | .sample_rate = SAMPLE_RATE, 103 | .bits_per_sample = 16, 104 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels 105 | .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, 106 | .dma_buf_count = 32, // number of buffers, 128 max. 107 | .dma_buf_len = 32 * 2, // size of each buffer 108 | .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1 109 | }; 110 | 111 | i2s_pin_config_t pin_config = { 112 | .bck_io_num = 26, 113 | .ws_io_num = 25, 114 | .data_out_num = 22, 115 | .data_in_num = I2S_PIN_NO_CHANGE // Not used 116 | }; 117 | 118 | i2s_driver_install(I2S_CHANNEL, &i2s_config, 1, &i2s_event_queue); 119 | i2s_set_pin(I2S_CHANNEL, &pin_config); 120 | i2s_set_sample_rates(I2S_CHANNEL, SAMPLE_RATE); 121 | i2s_stop(I2S_CHANNEL); 122 | } 123 | 124 | void audioplayer_start() { 125 | i2s_start(I2S_CHANNEL); 126 | i2s_zero_dma_buffer(I2S_CHANNEL); 127 | } 128 | 129 | static void i2c_example_master_init() 130 | { 131 | int i2c_master_port = I2C_EXAMPLE_MASTER_NUM; 132 | i2c_config_t conf; 133 | conf.mode = I2C_MODE_MASTER; 134 | conf.sda_io_num = I2C_EXAMPLE_MASTER_SDA_IO; 135 | conf.sda_pullup_en = GPIO_PULLUP_ENABLE; 136 | conf.scl_io_num = I2C_EXAMPLE_MASTER_SCL_IO; 137 | conf.scl_pullup_en = GPIO_PULLUP_ENABLE; 138 | conf.master.clk_speed = I2C_EXAMPLE_MASTER_FREQ_HZ; 139 | i2c_param_config(i2c_master_port, &conf); 140 | i2c_driver_install(i2c_master_port, conf.mode, 141 | I2C_EXAMPLE_MASTER_RX_BUF_DISABLE, 142 | I2C_EXAMPLE_MASTER_TX_BUF_DISABLE, 0); 143 | } 144 | 145 | void screen_loop(void *pvParameter) { 146 | while(1) { 147 | SSD1306_DrawFilledRectangle(0, 32, 128, 32, SSD1306_COLOR_BLACK); 148 | short *x = (short *)&waveform_buffer; 149 | for(int i=0; i<128; i++) { 150 | SSD1306_DrawPixel(i, 48 + (x[i] / 2000), SSD1306_COLOR_WHITE); 151 | } 152 | SSD1306_UpdateScreen(); 153 | vTaskDelay(4 / portTICK_PERIOD_MS); 154 | } 155 | } 156 | 157 | void app_main() { 158 | printf("-----------------------------------\n"); 159 | printf("HELLO WORLD\n"); 160 | printf("-----------------------------------\n"); 161 | 162 | i2c_example_master_init(); 163 | SSD1306_Init(); 164 | SSD1306_Fill(SSD1306_COLOR_BLACK); 165 | SSD1306_GotoXY(4, 4); 166 | SSD1306_Puts("ESP32-SID", &Font_11x18, SSD1306_COLOR_WHITE); 167 | SSD1306_UpdateScreen(); 168 | 169 | vTaskDelay(2000 / portTICK_PERIOD_MS); 170 | 171 | SSD1306_Fill(SSD1306_COLOR_BLACK); 172 | SSD1306_UpdateScreen(); 173 | 174 | audioplayer_init(); 175 | audioplayer_start(); 176 | 177 | libcsid_init(22050, SIDMODEL_6581); 178 | libcsid_load((unsigned char *)&music_Commando_sid, music_Commando_sid_len, 0); 179 | 180 | printf("SID Title: %s\n", libcsid_gettitle()); 181 | printf("SID Author: %s\n", libcsid_getauthor()); 182 | printf("SID Info: %s\n", libcsid_getinfo()); 183 | 184 | SSD1306_GotoXY(2, 2); 185 | SSD1306_Puts(libcsid_gettitle(), &Font_7x10, SSD1306_COLOR_WHITE); 186 | SSD1306_GotoXY(2, 16); 187 | SSD1306_Puts(libcsid_getauthor(), &Font_7x10, SSD1306_COLOR_WHITE); 188 | 189 | SSD1306_UpdateScreen(); 190 | 191 | xTaskCreate(&audiorenderer_loop, "audio", 16384, NULL, 5, NULL); 192 | xTaskCreate(&screen_loop, "screen", 16384, NULL, 35, NULL); 193 | } 194 | 195 | -------------------------------------------------------------------------------- /main/commando.inc: -------------------------------------------------------------------------------- 1 | unsigned char music_Commando_sid[] = { 2 | 0x50, 0x53, 0x49, 0x44, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x00, 0x5f, 0x80, 3 | 0x50, 0x12, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 4 | 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x6f, 0x62, 0x20, 0x48, 0x75, 7 | 0x62, 0x62, 0x61, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 9 | 0x00, 0x00, 0x31, 0x39, 0x38, 0x35, 0x20, 0x45, 0x6c, 0x69, 0x74, 0x65, 10 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 12 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4c, 0x0c, 0x5f, 0x4c, 0x42, 0x5f, 13 | 0x4c, 0x48, 0x5f, 0x4c, 0x4e, 0x5f, 0x4c, 0xcf, 0x53, 0x4c, 0x56, 0x5f, 14 | 0xee, 0x25, 0x55, 0x2c, 0x19, 0x55, 0x30, 0x1e, 0x50, 0x36, 0xa9, 0x00, 15 | 0x8d, 0x25, 0x55, 0xa2, 0x02, 0x9d, 0xec, 0x54, 0x9d, 0xef, 0x54, 0x9d, 16 | 0xf2, 0x54, 0x9d, 0xfb, 0x54, 0xca, 0x10, 0xf1, 0x8d, 0x19, 0x55, 0x4c, 17 | 0x52, 0x50, 0x50, 0x15, 0xa9, 0x00, 0x8d, 0x04, 0xd4, 0x8d, 0x0b, 0xd4, 18 | 0x8d, 0x12, 0xd4, 0xa9, 0x0f, 0x8d, 0x18, 0xd4, 0xa9, 0x80, 0x8d, 0x19, 19 | 0x55, 0x4c, 0xa5, 0x53, 0xa2, 0x02, 0xce, 0x13, 0x55, 0x10, 0x06, 0xad, 20 | 0x17, 0x55, 0x8d, 0x13, 0x55, 0xbd, 0xe8, 0x54, 0x8d, 0xeb, 0x54, 0xa8, 21 | 0xad, 0x13, 0x55, 0xcd, 0x17, 0x55, 0xd0, 0x15, 0xbd, 0xf9, 0x56, 0x85, 22 | 0x5d, 0xbd, 0xfc, 0x56, 0x85, 0x5e, 0xde, 0xf2, 0x54, 0x30, 0x09, 0x4c, 23 | 0x74, 0x51, 0x4c, 0x8f, 0x53, 0x4c, 0x9b, 0x51, 0xbc, 0xec, 0x54, 0xb1, 24 | 0x5d, 0xc9, 0xff, 0xf0, 0x0a, 0xc9, 0xfe, 0xd0, 0x17, 0x20, 0x03, 0x50, 25 | 0x4c, 0xa5, 0x53, 0xa9, 0x00, 0x9d, 0xf2, 0x54, 0x9d, 0xec, 0x54, 0x9d, 26 | 0xef, 0x54, 0x4c, 0x86, 0x50, 0x4c, 0x8f, 0x53, 0xa8, 0xb9, 0x11, 0x57, 27 | 0x85, 0x5f, 0xb9, 0x3e, 0x57, 0x85, 0x60, 0xa9, 0x00, 0x9d, 0x20, 0x55, 28 | 0xbc, 0xef, 0x54, 0xa9, 0xff, 0x8d, 0x01, 0x55, 0xb1, 0x5f, 0x9d, 0xf5, 29 | 0x54, 0x8d, 0x02, 0x55, 0x29, 0x1f, 0x9d, 0xf2, 0x54, 0x2c, 0x02, 0x55, 30 | 0x70, 0x44, 0xfe, 0xef, 0x54, 0xad, 0x02, 0x55, 0x10, 0x11, 0xc8, 0xb1, 31 | 0x5f, 0x10, 0x06, 0x9d, 0x20, 0x55, 0x4c, 0xea, 0x50, 0x9d, 0xfe, 0x54, 32 | 0xfe, 0xef, 0x54, 0xc8, 0xb1, 0x5f, 0x9d, 0xfb, 0x54, 0x0a, 0xa8, 0xad, 33 | 0x28, 0x55, 0x10, 0x21, 0xb9, 0x28, 0x54, 0x8d, 0x03, 0x55, 0xb9, 0x29, 34 | 0x54, 0xac, 0xeb, 0x54, 0x99, 0x01, 0xd4, 0x9d, 0x1a, 0x55, 0xad, 0x03, 35 | 0x55, 0x99, 0x00, 0xd4, 0x9d, 0x1d, 0x55, 0x4c, 0x1b, 0x51, 0xce, 0x01, 36 | 0x55, 0xac, 0xeb, 0x54, 0xbd, 0xfe, 0x54, 0x8e, 0x04, 0x55, 0x0a, 0x0a, 37 | 0x0a, 0xaa, 0xbd, 0x93, 0x55, 0x8d, 0x05, 0x55, 0xad, 0x28, 0x55, 0x10, 38 | 0x21, 0xbd, 0x93, 0x55, 0x2d, 0x01, 0x55, 0x99, 0x04, 0xd4, 0xbd, 0x91, 39 | 0x55, 0x99, 0x02, 0xd4, 0xbd, 0x92, 0x55, 0x99, 0x03, 0xd4, 0xbd, 0x94, 40 | 0x55, 0x99, 0x05, 0xd4, 0xbd, 0x95, 0x55, 0x99, 0x06, 0xd4, 0xae, 0x04, 41 | 0x55, 0xad, 0x05, 0x55, 0x9d, 0xf8, 0x54, 0xfe, 0xef, 0x54, 0xbc, 0xef, 42 | 0x54, 0xb1, 0x5f, 0xc9, 0xff, 0xd0, 0x08, 0xa9, 0x00, 0x9d, 0xef, 0x54, 43 | 0xfe, 0xec, 0x54, 0x4c, 0x8f, 0x53, 0xad, 0x28, 0x55, 0x30, 0x03, 0x4c, 44 | 0x8f, 0x53, 0xac, 0xeb, 0x54, 0xbd, 0xf5, 0x54, 0x29, 0x20, 0xd0, 0x15, 45 | 0xbd, 0xf2, 0x54, 0xd0, 0x10, 0xbd, 0xf8, 0x54, 0x29, 0xfe, 0x99, 0x04, 46 | 0xd4, 0xa9, 0x00, 0x99, 0x05, 0xd4, 0x99, 0x06, 0xd4, 0xad, 0x28, 0x55, 47 | 0x30, 0x03, 0x4c, 0x8f, 0x53, 0xbd, 0xfe, 0x54, 0x0a, 0x0a, 0x0a, 0xa8, 48 | 0x8c, 0x18, 0x55, 0xb9, 0x98, 0x55, 0x8d, 0x23, 0x55, 0xb9, 0x97, 0x55, 49 | 0x8d, 0x07, 0x55, 0xb9, 0x96, 0x55, 0x8d, 0x06, 0x55, 0xf0, 0x6f, 0xad, 50 | 0x25, 0x55, 0x29, 0x07, 0xc9, 0x04, 0x90, 0x02, 0x49, 0x07, 0x8d, 0x0c, 51 | 0x55, 0xbd, 0xfb, 0x54, 0x0a, 0xa8, 0x38, 0xb9, 0x2a, 0x54, 0xf9, 0x28, 52 | 0x54, 0x8d, 0x08, 0x55, 0xb9, 0x2b, 0x54, 0xf9, 0x29, 0x54, 0x4a, 0x6e, 53 | 0x08, 0x55, 0xce, 0x06, 0x55, 0x10, 0xf7, 0x8d, 0x09, 0x55, 0xb9, 0x28, 54 | 0x54, 0x8d, 0x0a, 0x55, 0xb9, 0x29, 0x54, 0x8d, 0x0b, 0x55, 0xbd, 0xf5, 55 | 0x54, 0x29, 0x1f, 0xc9, 0x06, 0x90, 0x1c, 0xac, 0x0c, 0x55, 0x88, 0x30, 56 | 0x16, 0x18, 0xad, 0x0a, 0x55, 0x6d, 0x08, 0x55, 0x8d, 0x0a, 0x55, 0xad, 57 | 0x0b, 0x55, 0x6d, 0x09, 0x55, 0x8d, 0x0b, 0x55, 0x4c, 0x08, 0x52, 0xac, 58 | 0xeb, 0x54, 0xad, 0x0a, 0x55, 0x99, 0x00, 0xd4, 0xad, 0x0b, 0x55, 0x99, 59 | 0x01, 0xd4, 0xad, 0x23, 0x55, 0x29, 0x08, 0xf0, 0x15, 0xac, 0x18, 0x55, 60 | 0xb9, 0x91, 0x55, 0x6d, 0x07, 0x55, 0x99, 0x91, 0x55, 0xac, 0xeb, 0x54, 61 | 0x99, 0x02, 0xd4, 0x4c, 0xb3, 0x52, 0xad, 0x07, 0x55, 0xf0, 0x62, 0xac, 62 | 0x18, 0x55, 0x29, 0x1f, 0xde, 0x0d, 0x55, 0x10, 0x58, 0x9d, 0x0d, 0x55, 63 | 0xad, 0x07, 0x55, 0x29, 0xe0, 0x8d, 0x24, 0x55, 0xbd, 0x10, 0x55, 0xd0, 64 | 0x1a, 0xad, 0x24, 0x55, 0x18, 0x79, 0x91, 0x55, 0x48, 0xb9, 0x92, 0x55, 65 | 0x69, 0x00, 0x29, 0x0f, 0x48, 0xc9, 0x0e, 0xd0, 0x1d, 0xfe, 0x10, 0x55, 66 | 0x4c, 0x9c, 0x52, 0x38, 0xb9, 0x91, 0x55, 0xed, 0x24, 0x55, 0x48, 0xb9, 67 | 0x92, 0x55, 0xe9, 0x00, 0x29, 0x0f, 0x48, 0xc9, 0x08, 0xd0, 0x03, 0xde, 68 | 0x10, 0x55, 0x8e, 0x04, 0x55, 0xae, 0xeb, 0x54, 0x68, 0x99, 0x92, 0x55, 69 | 0x9d, 0x03, 0xd4, 0x68, 0x99, 0x91, 0x55, 0x9d, 0x02, 0xd4, 0xae, 0x04, 70 | 0x55, 0xac, 0xeb, 0x54, 0xbd, 0x20, 0x55, 0xf0, 0x3f, 0x29, 0x7e, 0x8d, 71 | 0x04, 0x55, 0xbd, 0x20, 0x55, 0x29, 0x01, 0xf0, 0x1b, 0x38, 0xbd, 0x1d, 72 | 0x55, 0xed, 0x04, 0x55, 0x9d, 0x1d, 0x55, 0x99, 0x00, 0xd4, 0xbd, 0x1a, 73 | 0x55, 0xe9, 0x00, 0x9d, 0x1a, 0x55, 0x99, 0x01, 0xd4, 0x4c, 0xfa, 0x52, 74 | 0x18, 0xbd, 0x1d, 0x55, 0x6d, 0x04, 0x55, 0x9d, 0x1d, 0x55, 0x99, 0x00, 75 | 0xd4, 0xbd, 0x1a, 0x55, 0x69, 0x00, 0x9d, 0x1a, 0x55, 0x99, 0x01, 0xd4, 76 | 0xad, 0x23, 0x55, 0x29, 0x01, 0xf0, 0x35, 0xbd, 0x1a, 0x55, 0xf0, 0x30, 77 | 0xbd, 0xf2, 0x54, 0xf0, 0x2b, 0xbd, 0xf5, 0x54, 0x29, 0x1f, 0x38, 0xe9, 78 | 0x01, 0xdd, 0xf2, 0x54, 0xac, 0xeb, 0x54, 0x90, 0x10, 0xbd, 0x1a, 0x55, 79 | 0xde, 0x1a, 0x55, 0x99, 0x01, 0xd4, 0xbd, 0xf8, 0x54, 0x29, 0xfe, 0xd0, 80 | 0x08, 0xbd, 0x1a, 0x55, 0x99, 0x01, 0xd4, 0xa9, 0x80, 0x99, 0x04, 0xd4, 81 | 0xad, 0x23, 0x55, 0x29, 0x02, 0xf0, 0x21, 0xbd, 0xf5, 0x54, 0x29, 0x1f, 82 | 0xc9, 0x03, 0x90, 0x18, 0xad, 0x25, 0x55, 0x29, 0x01, 0xf0, 0x11, 0xbd, 83 | 0x1a, 0x55, 0xf0, 0x0c, 0xfe, 0x1a, 0x55, 0xfe, 0x1a, 0x55, 0xac, 0xeb, 84 | 0x54, 0x99, 0x01, 0xd4, 0xad, 0x23, 0x55, 0x29, 0x04, 0xf0, 0x2a, 0xad, 85 | 0x25, 0x55, 0x29, 0x01, 0xf0, 0x09, 0xbd, 0xfb, 0x54, 0x18, 0x69, 0x0c, 86 | 0x4c, 0x78, 0x53, 0xbd, 0xfb, 0x54, 0x0a, 0xa8, 0xb9, 0x28, 0x54, 0x8d, 87 | 0x03, 0x55, 0xb9, 0x29, 0x54, 0xac, 0xeb, 0x54, 0x99, 0x01, 0xd4, 0xad, 88 | 0x03, 0x55, 0x99, 0x00, 0xd4, 0xa0, 0xff, 0xad, 0x26, 0x55, 0xd0, 0x06, 89 | 0xad, 0x27, 0x55, 0x30, 0x01, 0xc8, 0x8c, 0x28, 0x55, 0xca, 0x30, 0x03, 90 | 0x4c, 0x5f, 0x50, 0xa9, 0xff, 0x8d, 0x28, 0x55, 0xad, 0x26, 0x55, 0xd0, 91 | 0x05, 0x2c, 0x27, 0x55, 0x10, 0x01, 0x60, 0x50, 0x03, 0x20, 0x31, 0x55, 92 | 0xce, 0x2a, 0x55, 0x10, 0xf5, 0xad, 0x30, 0x55, 0x29, 0x0f, 0x8d, 0x2a, 93 | 0x55, 0xad, 0x29, 0x55, 0xcd, 0x2b, 0x55, 0xd0, 0x0f, 0xa2, 0x00, 0x8e, 94 | 0x04, 0xd4, 0x8e, 0x0b, 0xd4, 0xca, 0x8e, 0x27, 0x55, 0x4c, 0xb4, 0x53, 95 | 0xce, 0x29, 0x55, 0x0a, 0xa8, 0x2c, 0x30, 0x55, 0x30, 0x20, 0x70, 0x0c, 96 | 0xb9, 0x28, 0x54, 0x8d, 0x00, 0xd4, 0xb9, 0x29, 0x54, 0x8d, 0x01, 0xd4, 97 | 0x98, 0x38, 0xed, 0x2c, 0x55, 0xa8, 0xb9, 0x28, 0x54, 0x8d, 0x07, 0xd4, 98 | 0xb9, 0x29, 0x54, 0x8d, 0x08, 0xd4, 0x2c, 0x2d, 0x55, 0x10, 0x0b, 0xad, 99 | 0x2e, 0x55, 0x49, 0x01, 0x8d, 0x04, 0xd4, 0x8d, 0x2e, 0x55, 0x50, 0x0b, 100 | 0xad, 0x2f, 0x55, 0x49, 0x01, 0x8d, 0x0b, 0xd4, 0x8d, 0x2f, 0x55, 0x4c, 101 | 0xb4, 0x53, 0x16, 0x01, 0x27, 0x01, 0x38, 0x01, 0x4b, 0x01, 0x5f, 0x01, 102 | 0x73, 0x01, 0x8a, 0x01, 0xa1, 0x01, 0xba, 0x01, 0xd4, 0x01, 0xf0, 0x01, 103 | 0x0e, 0x02, 0x2d, 0x02, 0x4e, 0x02, 0x71, 0x02, 0x96, 0x02, 0xbd, 0x02, 104 | 0xe7, 0x02, 0x13, 0x03, 0x42, 0x03, 0x74, 0x03, 0xa9, 0x03, 0xe0, 0x03, 105 | 0x1b, 0x04, 0x5a, 0x04, 0x9b, 0x04, 0xe2, 0x04, 0x2c, 0x05, 0x7b, 0x05, 106 | 0xce, 0x05, 0x27, 0x06, 0x85, 0x06, 0xe8, 0x06, 0x51, 0x07, 0xc1, 0x07, 107 | 0x37, 0x08, 0xb4, 0x08, 0x37, 0x09, 0xc4, 0x09, 0x57, 0x0a, 0xf5, 0x0a, 108 | 0x9c, 0x0b, 0x4e, 0x0c, 0x09, 0x0d, 0xd0, 0x0d, 0xa3, 0x0e, 0x82, 0x0f, 109 | 0x6e, 0x10, 0x68, 0x11, 0x6e, 0x12, 0x88, 0x13, 0xaf, 0x14, 0xeb, 0x15, 110 | 0x39, 0x17, 0x9c, 0x18, 0x13, 0x1a, 0xa1, 0x1b, 0x46, 0x1d, 0x04, 0x1f, 111 | 0xdc, 0x20, 0xd0, 0x22, 0xdc, 0x24, 0x10, 0x27, 0x5e, 0x29, 0xd6, 0x2b, 112 | 0x72, 0x2e, 0x38, 0x31, 0x26, 0x34, 0x42, 0x37, 0x8c, 0x3a, 0x08, 0x3e, 113 | 0xb8, 0x41, 0xa0, 0x45, 0xb8, 0x49, 0x20, 0x4e, 0xbc, 0x52, 0xac, 0x57, 114 | 0xe4, 0x5c, 0x70, 0x62, 0x4c, 0x68, 0x84, 0x6e, 0x18, 0x75, 0x10, 0x7c, 115 | 0x70, 0x83, 0x40, 0x8b, 0x70, 0x93, 0x40, 0x9c, 0x78, 0xa5, 0x58, 0xaf, 116 | 0xc8, 0xb9, 0xe0, 0xc4, 0x98, 0xd0, 0x08, 0xdd, 0x30, 0xea, 0x20, 0xf8, 117 | 0x2e, 0xfd, 0x00, 0x07, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0b, 118 | 0x05, 0x01, 0x05, 0x97, 0x03, 0x07, 0x41, 0x21, 0x41, 0x3d, 0x39, 0x15, 119 | 0x08, 0x09, 0x02, 0xff, 0x03, 0x46, 0x01, 0x21, 0xff, 0x03, 0x46, 0x00, 120 | 0x22, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 121 | 0x02, 0x03, 0x40, 0x00, 0x24, 0x16, 0x03, 0xdc, 0x46, 0xa9, 0x00, 0x00, 122 | 0x00, 0x08, 0xe0, 0x56, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 123 | 0x00, 0x00, 0x00, 0xa9, 0x00, 0x8d, 0x04, 0xd4, 0x8d, 0x0b, 0xd4, 0x8d, 124 | 0x2a, 0x55, 0xad, 0x27, 0x55, 0x29, 0x0f, 0x8d, 0x27, 0x55, 0x0a, 0x0a, 125 | 0x0a, 0x0a, 0xa8, 0xb9, 0xf9, 0x55, 0x8d, 0x30, 0x55, 0xb9, 0xfa, 0x55, 126 | 0x8d, 0x29, 0x55, 0xb9, 0x08, 0x56, 0x8d, 0x2b, 0x55, 0xb9, 0x01, 0x56, 127 | 0x8d, 0x2d, 0x55, 0x29, 0x3f, 0x8d, 0x2c, 0x55, 0xb9, 0xfe, 0x55, 0x8d, 128 | 0x2e, 0x55, 0xb9, 0x05, 0x56, 0x8d, 0x2f, 0x55, 0xa2, 0x00, 0xb9, 0xfa, 129 | 0x55, 0x9d, 0x00, 0xd4, 0xc8, 0xe8, 0xe0, 0x0e, 0xd0, 0xf4, 0xad, 0x30, 130 | 0x55, 0x29, 0x30, 0xa0, 0xee, 0xc9, 0x20, 0xf0, 0x02, 0xa0, 0xce, 0x8c, 131 | 0xde, 0x53, 0x60, 0xc0, 0x0a, 0x41, 0x29, 0x5f, 0x02, 0xe0, 0x00, 0x80, 132 | 0x01, 0x41, 0x06, 0x4b, 0x00, 0x00, 0x05, 0x52, 0x01, 0x41, 0x09, 0x9f, 133 | 0x00, 0x16, 0x08, 0x00, 0x02, 0x81, 0x0a, 0x09, 0x00, 0x00, 0x05, 0x00, 134 | 0x02, 0x43, 0x0f, 0xc4, 0x00, 0x00, 0x03, 0xda, 0x08, 0x41, 0x05, 0xa9, 135 | 0x00, 0x02, 0x0d, 0xe0, 0x0a, 0x41, 0x38, 0x7a, 0x02, 0xe0, 0x00, 0x80, 136 | 0x01, 0x15, 0x0d, 0xfb, 0x01, 0x00, 0x05, 0xb4, 0x08, 0x41, 0x49, 0x5b, 137 | 0x02, 0x03, 0x08, 0x00, 0x08, 0x21, 0x04, 0x6f, 0x03, 0x00, 0x05, 0x7f, 138 | 0x03, 0x41, 0x09, 0x6b, 0x02, 0x01, 0x0d, 0x00, 0x02, 0x43, 0x07, 0x09, 139 | 0x01, 0x00, 0x01, 0x00, 0x08, 0x41, 0x09, 0x0a, 0x00, 0x00, 0x01, 0x10, 140 | 0x50, 0x24, 0x80, 0x11, 0x11, 0x7c, 0x30, 0x11, 0x00, 0x80, 0x08, 0x15, 141 | 0x4c, 0x00, 0x18, 0x60, 0x38, 0x58, 0x80, 0x11, 0x81, 0x0a, 0x30, 0x00, 142 | 0x00, 0x80, 0x08, 0x15, 0x0a, 0x90, 0x58, 0x51, 0x3f, 0x0f, 0x80, 0x11, 143 | 0x81, 0x0a, 0x10, 0x20, 0x00, 0x80, 0x08, 0x81, 0x0a, 0x10, 0x27, 0x11, 144 | 0x6f, 0x50, 0x00, 0x08, 0x41, 0x0d, 0x40, 0x03, 0x0f, 0x80, 0x08, 0x15, 145 | 0x0d, 0x40, 0x00, 0x11, 0x5f, 0x00, 0x80, 0x08, 0x41, 0x00, 0xc0, 0xc4, 146 | 0x00, 0x80, 0x08, 0x41, 0x00, 0xc0, 0x30, 0xa3, 0x33, 0x01, 0x00, 0x00, 147 | 0x51, 0x0f, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x57, 0x0f, 0xf0, 0x5f, 0x66, 148 | 0x00, 0x02, 0x00, 0x00, 0x51, 0x0f, 0xf0, 0x00, 0x03, 0x00, 0x00, 0x57, 149 | 0x0f, 0xf0, 0x28, 0x61, 0x00, 0x07, 0x80, 0x02, 0x41, 0x00, 0xff, 0x00, 150 | 0x27, 0x00, 0x04, 0x43, 0x00, 0xff, 0x4f, 0x12, 0x30, 0x08, 0x00, 0x01, 151 | 0x81, 0x0c, 0x40, 0x04, 0x04, 0x00, 0x08, 0x15, 0x0c, 0x00, 0x10, 0x61, 152 | 0x00, 0x18, 0x00, 0x08, 0x81, 0x07, 0x00, 0xc5, 0x01, 0x00, 0x02, 0x85, 153 | 0x06, 0x00, 0x48, 0x50, 0x30, 0x14, 0x00, 0x08, 0x81, 0x0c, 0x00, 0x25, 154 | 0x01, 0x00, 0x01, 0x43, 0x0a, 0x00, 0x08, 0x50, 0x5f, 0x20, 0x80, 0x08, 155 | 0x81, 0x0b, 0x00, 0x00, 0x27, 0x00, 0x02, 0x15, 0x0a, 0x00, 0x27, 0x22, 156 | 0x26, 0x14, 0x80, 0x03, 0x41, 0x0d, 0x00, 0x06, 0x10, 0x00, 0x06, 0x41, 157 | 0x0d, 0x00, 0x53, 0xa2, 0x00, 0x18, 0x80, 0x08, 0x41, 0x09, 0x20, 0xce, 158 | 0x37, 0x00, 0x02, 0x15, 0x09, 0x10, 0x26, 0xa2, 0x36, 0x0a, 0x80, 0x08, 159 | 0x81, 0x0a, 0x00, 0x00, 0x17, 0xa0, 0x02, 0x81, 0x0a, 0x00, 0x4f, 0x50, 160 | 0x30, 0x09, 0x80, 0x08, 0x81, 0x09, 0x00, 0x00, 0x02, 0x00, 0x02, 0x81, 161 | 0x09, 0x00, 0x07, 0x68, 0x72, 0x74, 0x58, 0x58, 0x58, 0x6b, 0xac, 0xec, 162 | 0x57, 0x57, 0x57, 0x68, 0x72, 0x74, 0x58, 0x58, 0x58, 0x7e, 0x81, 0x84, 163 | 0x58, 0x58, 0x58, 0x87, 0xcd, 0xe3, 0xf9, 0x0f, 0x25, 0x3b, 0x89, 0xfa, 164 | 0x88, 0x41, 0x51, 0xd2, 0x67, 0x7d, 0x26, 0x5d, 0x73, 0x91, 0xcd, 0xf1, 165 | 0x15, 0x39, 0x5d, 0x7d, 0x9d, 0xba, 0x4a, 0x78, 0x91, 0xaa, 0xc3, 0x93, 166 | 0xb4, 0xd5, 0xf6, 0x17, 0x29, 0x34, 0x3d, 0x5c, 0x7f, 0x91, 0xba, 0xe3, 167 | 0x58, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x58, 0x58, 0x59, 0x59, 0x5d, 168 | 0x59, 0x5d, 0x5d, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 169 | 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d, 170 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x13, 0x13, 0x13, 171 | 0x13, 0x07, 0x07, 0x09, 0x0c, 0x0c, 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f, 172 | 0x11, 0x11, 0x12, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x10, 173 | 0x10, 0x10, 0x10, 0x17, 0x17, 0x17, 0x17, 0x10, 0x10, 0x17, 0x17, 0x1a, 174 | 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 175 | 0x1e, 0x0f, 0x17, 0x17, 0x1f, 0x10, 0x10, 0x17, 0x11, 0x17, 0x12, 0x17, 176 | 0x1f, 0xff, 0x08, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x08, 0x08, 0x08, 0x13, 177 | 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x18, 0x18, 0x18, 178 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x13, 0x13, 0x18, 0x18, 0x18, 0x18, 0x13, 179 | 0x18, 0x18, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 180 | 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x18, 0x18, 0x1f, 0x13, 0x18, 0x15, 181 | 0x18, 0x16, 0x16, 0x18, 0x1f, 0xff, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 182 | 0x02, 0x03, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x01, 0x01, 183 | 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x01, 0x0b, 0x03, 0x01, 0x01, 0x01, 184 | 0x02, 0x03, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 185 | 0x0e, 0x0e, 0x0d, 0x0d, 0x0e, 0x0e, 0x0b, 0x0b, 0x0b, 0x0b, 0x03, 0x03, 186 | 0x03, 0x03, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x01, 0x01, 187 | 0x0b, 0x0b, 0x19, 0x19, 0x19, 0x19, 0x01, 0x0b, 0x19, 0x19, 0x01, 0x01, 188 | 0x0b, 0x0b, 0x01, 0x01, 0x0b, 0x0b, 0x01, 0x01, 0x0b, 0x0b, 0x01, 0x01, 189 | 0x0b, 0x0b, 0x01, 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, 0x0d, 0x0d, 190 | 0x0e, 0x0e, 0x0d, 0x0d, 0x0e, 0x0e, 0x19, 0x19, 0x1f, 0x01, 0x0b, 0x19, 191 | 0x0b, 0x0b, 0x19, 0x03, 0x03, 0x03, 0x03, 0x19, 0x1f, 0xff, 0x24, 0x25, 192 | 0x24, 0x26, 0x27, 0x24, 0x26, 0x28, 0x28, 0xff, 0x29, 0xff, 0x20, 0x20, 193 | 0x22, 0x21, 0x20, 0x23, 0x23, 0x23, 0x23, 0xff, 0x2a, 0x00, 0xfe, 0x2b, 194 | 0x00, 0xfe, 0x2c, 0x00, 0xfe, 0x5f, 0xff, 0x81, 0x03, 0x32, 0x81, 0x00, 195 | 0x39, 0x03, 0x39, 0x03, 0x39, 0x03, 0x39, 0x07, 0x39, 0x05, 0x39, 0x03, 196 | 0x39, 0x01, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x07, 0x40, 0x87, 197 | 0x0c, 0x2c, 0x87, 0x00, 0x41, 0x07, 0x40, 0x07, 0x41, 0x07, 0x40, 0x41, 198 | 0x01, 0x3b, 0x03, 0x3b, 0x03, 0x3b, 0x03, 0x3b, 0x07, 0x3b, 0x87, 0x0c, 199 | 0x2c, 0x81, 0x03, 0x32, 0x81, 0x00, 0x3c, 0x03, 0x3c, 0x03, 0x3c, 0x03, 200 | 0x3c, 0x07, 0x3c, 0x05, 0x3c, 0x03, 0x3c, 0x01, 0x43, 0x03, 0x43, 0x03, 201 | 0x43, 0x03, 0x43, 0x07, 0x43, 0x87, 0x0c, 0x2c, 0x87, 0x00, 0x44, 0x07, 202 | 0x43, 0x07, 0x44, 0x07, 0x43, 0x41, 0x01, 0x3e, 0x03, 0x3e, 0x03, 0x3e, 203 | 0x03, 0x3e, 0x07, 0x3e, 0x83, 0x0c, 0x2f, 0x01, 0x2c, 0x01, 0x2c, 0xff, 204 | 0x81, 0x04, 0x68, 0x01, 0x68, 0x01, 0x68, 0x01, 0x68, 0x83, 0x01, 0x34, 205 | 0x03, 0x34, 0x05, 0x35, 0x05, 0x34, 0x03, 0x32, 0x81, 0x04, 0x68, 0x01, 206 | 0x68, 0x01, 0x68, 0x01, 0x68, 0x83, 0x01, 0x34, 0x03, 0x34, 0x07, 0x34, 207 | 0x47, 0x81, 0x04, 0x68, 0x01, 0x68, 0x01, 0x68, 0x01, 0x68, 0x83, 0x01, 208 | 0x34, 0x03, 0x34, 0x05, 0x35, 0x05, 0x34, 0x03, 0x32, 0x41, 0x81, 0x01, 209 | 0x34, 0x03, 0x34, 0x03, 0x34, 0x03, 0x34, 0x07, 0x34, 0x47, 0xff, 0x81, 210 | 0x04, 0x68, 0x01, 0x68, 0x01, 0x68, 0x01, 0x68, 0x83, 0x01, 0x37, 0x03, 211 | 0x37, 0x05, 0x38, 0x05, 0x37, 0x03, 0x35, 0x81, 0x04, 0x68, 0x01, 0x68, 212 | 0x01, 0x68, 0x01, 0x68, 0x83, 0x01, 0x37, 0x03, 0x37, 0x07, 0x37, 0x47, 213 | 0x81, 0x04, 0x68, 0x01, 0x68, 0x01, 0x68, 0x01, 0x68, 0x83, 0x01, 0x37, 214 | 0x03, 0x37, 0x05, 0x38, 0x05, 0x37, 0x03, 0x35, 0x41, 0x81, 0x01, 0x37, 215 | 0x03, 0x37, 0x03, 0x37, 0x03, 0x37, 0x07, 0x37, 0x47, 0xff, 0x83, 0x03, 216 | 0x32, 0x03, 0x32, 0x83, 0x00, 0x39, 0x03, 0x39, 0x01, 0x39, 0x01, 0x39, 217 | 0x03, 0x39, 0x03, 0x3b, 0x03, 0x3c, 0x01, 0x3e, 0x01, 0x3e, 0x03, 0x3e, 218 | 0x03, 0x3e, 0x03, 0x3e, 0x07, 0x3e, 0x83, 0x0c, 0x2c, 0x81, 0x00, 0x3e, 219 | 0x01, 0x40, 0x01, 0x41, 0x01, 0x41, 0x03, 0x40, 0x03, 0x3e, 0x03, 0x3c, 220 | 0x03, 0x3b, 0x03, 0x39, 0x07, 0x38, 0x81, 0x03, 0x32, 0x81, 0x00, 0x39, 221 | 0x03, 0x39, 0x03, 0x39, 0x03, 0x3b, 0x07, 0x39, 0x87, 0x0c, 0x2c, 0xff, 222 | 0x81, 0x05, 0x3c, 0x03, 0x3b, 0x01, 0x3a, 0x03, 0x39, 0x01, 0x3c, 0x03, 223 | 0x3b, 0x01, 0x3a, 0x03, 0x39, 0x01, 0x3c, 0x03, 0x3b, 0x01, 0x3a, 0x03, 224 | 0x39, 0x01, 0x3c, 0x03, 0x3b, 0x01, 0x3a, 0x03, 0x39, 0x01, 0x3c, 0x03, 225 | 0x3b, 0x01, 0x39, 0x03, 0x41, 0x03, 0x40, 0x01, 0x41, 0x03, 0x40, 0x01, 226 | 0x3f, 0x03, 0x3e, 0x01, 0x41, 0x03, 0x40, 0x01, 0x3f, 0x03, 0x3e, 0x03, 227 | 0x41, 0x03, 0x40, 0x01, 0x3b, 0x03, 0x3a, 0x01, 0x39, 0x03, 0x38, 0x01, 228 | 0x3b, 0x03, 0x3a, 0x01, 0x39, 0x03, 0x38, 0x03, 0x3c, 0x03, 0x3b, 0xff, 229 | 0x8b, 0x06, 0x42, 0xa3, 0xcf, 0x42, 0x07, 0x40, 0x03, 0x3d, 0x03, 0x3b, 230 | 0xa3, 0xbf, 0x3b, 0x03, 0x3a, 0x03, 0x3a, 0x83, 0x0c, 0x2c, 0x03, 0x2c, 231 | 0x81, 0x06, 0x3a, 0x01, 0x3a, 0x03, 0x3b, 0x03, 0x3d, 0x0b, 0x3d, 0x03, 232 | 0x3d, 0x05, 0x40, 0x05, 0x3d, 0xa3, 0xa8, 0x3b, 0x07, 0x3d, 0x8f, 0xd1, 233 | 0x3d, 0x83, 0x0c, 0x2c, 0x03, 0x2c, 0xff, 0x81, 0x06, 0x3c, 0x03, 0x3b, 234 | 0x01, 0x3a, 0x03, 0x39, 0x01, 0x3c, 0x03, 0x3b, 0x01, 0x3a, 0x03, 0x39, 235 | 0x03, 0x3c, 0x03, 0x3e, 0xff, 0x87, 0x06, 0x3e, 0x83, 0x0c, 0x2c, 0x81, 236 | 0x06, 0x3e, 0x01, 0x3e, 0x05, 0x40, 0x05, 0x3e, 0xa3, 0xa8, 0x3c, 0x07, 237 | 0x3e, 0x83, 0x0c, 0x2f, 0x0b, 0x2c, 0x03, 0x2f, 0x03, 0x2c, 0xff, 0x87, 238 | 0x06, 0x40, 0x83, 0x0c, 0x2c, 0x81, 0x06, 0x40, 0x01, 0x40, 0x05, 0x42, 239 | 0x05, 0x40, 0xa3, 0xa8, 0x3e, 0x07, 0x40, 0x83, 0x0c, 0x2f, 0x0b, 0x2c, 240 | 0x03, 0x2f, 0x03, 0x2c, 0x87, 0x06, 0x40, 0x83, 0x0c, 0x2c, 0x81, 0x06, 241 | 0x40, 0x01, 0x40, 0x05, 0x42, 0x05, 0x40, 0xa3, 0xa8, 0x3e, 0x05, 0x40, 242 | 0x05, 0x42, 0x03, 0x44, 0x05, 0x42, 0x05, 0x44, 0x03, 0x45, 0xff, 0x83, 243 | 0x07, 0x58, 0x03, 0x51, 0x83, 0x01, 0x39, 0x03, 0x39, 0x05, 0x39, 0x05, 244 | 0x39, 0x05, 0x37, 0x01, 0x39, 0x03, 0x39, 0x03, 0x39, 0x03, 0x37, 0x01, 245 | 0x39, 0x01, 0x37, 0x03, 0x39, 0x83, 0x07, 0x58, 0x03, 0x51, 0xff, 0x83, 246 | 0x07, 0x55, 0x03, 0x4e, 0x83, 0x01, 0x31, 0x03, 0x31, 0x05, 0x31, 0x05, 247 | 0x31, 0x05, 0x2f, 0x01, 0x31, 0x03, 0x31, 0x03, 0x31, 0x03, 0x2f, 0x01, 248 | 0x31, 0x01, 0x2f, 0x03, 0x31, 0x83, 0x07, 0x55, 0x03, 0x4e, 0xff, 0x83, 249 | 0x07, 0x5d, 0x03, 0x56, 0x83, 0x01, 0x32, 0x03, 0x32, 0x05, 0x32, 0x05, 250 | 0x32, 0x05, 0x30, 0x01, 0x32, 0x03, 0x32, 0x03, 0x32, 0x03, 0x30, 0x01, 251 | 0x32, 0x01, 0x30, 0x03, 0x32, 0x83, 0x07, 0x5d, 0x03, 0x56, 0xff, 0x83, 252 | 0x07, 0x5f, 0x03, 0x58, 0x83, 0x01, 0x34, 0x03, 0x34, 0x05, 0x34, 0x05, 253 | 0x34, 0x05, 0x32, 0x01, 0x34, 0x03, 0x34, 0x03, 0x34, 0x03, 0x32, 0x01, 254 | 0x34, 0x01, 0x32, 0x03, 0x34, 0x83, 0x07, 0x5f, 0x03, 0x58, 0xff, 0x81, 255 | 0x05, 0x46, 0x01, 0x46, 0x01, 0x46, 0x01, 0x46, 0x01, 0x46, 0x01, 0x46, 256 | 0x01, 0x44, 0x01, 0x46, 0x01, 0x46, 0x01, 0x44, 0x03, 0x46, 0x01, 0x46, 257 | 0x01, 0x46, 0x01, 0x44, 0x01, 0x44, 0xff, 0x81, 0x05, 0x43, 0x01, 0x43, 258 | 0x01, 0x43, 0x01, 0x43, 0x01, 0x43, 0x01, 0x43, 0x01, 0x41, 0x01, 0x43, 259 | 0x01, 0x43, 0x01, 0x41, 0x03, 0x43, 0x01, 0x43, 0x01, 0x43, 0x01, 0x41, 260 | 0x01, 0x41, 0xff, 0x81, 0x05, 0x27, 0x01, 0x27, 0x01, 0x27, 0x01, 0x27, 261 | 0x83, 0x0c, 0x2c, 0x81, 0x05, 0x25, 0x03, 0x27, 0x01, 0x25, 0x01, 0x27, 262 | 0x01, 0x27, 0x83, 0x0c, 0x2f, 0x03, 0x2c, 0xff, 0xa7, 0x06, 0x37, 0xa7, 263 | 0xa8, 0x37, 0x17, 0x39, 0x03, 0x37, 0x03, 0x39, 0x03, 0x3e, 0x03, 0x3c, 264 | 0x07, 0x39, 0x27, 0x3c, 0xa7, 0xaa, 0x3c, 0x17, 0x3e, 0x03, 0x3e, 0x03, 265 | 0x43, 0x03, 0x42, 0x03, 0x3e, 0x07, 0x39, 0x27, 0x37, 0xa7, 0x90, 0x37, 266 | 0x17, 0x39, 0xa7, 0xa9, 0x3f, 0x03, 0x3e, 0x03, 0x3c, 0x07, 0x39, 0x27, 267 | 0x3e, 0xa7, 0xa9, 0x3e, 0x17, 0x3c, 0x03, 0x3e, 0x03, 0x40, 0x03, 0x43, 268 | 0x03, 0x42, 0x03, 0x43, 0x03, 0x45, 0x27, 0x43, 0xa7, 0xb4, 0x43, 0x07, 269 | 0x45, 0x01, 0x45, 0x03, 0x45, 0x01, 0x45, 0x01, 0x45, 0x03, 0x45, 0x01, 270 | 0x43, 0x03, 0x45, 0x01, 0x43, 0x03, 0x42, 0x01, 0x43, 0x03, 0x42, 0x03, 271 | 0x40, 0x03, 0x3e, 0x01, 0x3e, 0x03, 0x3e, 0x01, 0x3c, 0x03, 0x3e, 0x01, 272 | 0x3c, 0x03, 0x3b, 0x01, 0x3c, 0x03, 0x3b, 0x03, 0x39, 0x03, 0x37, 0x01, 273 | 0x39, 0x03, 0x39, 0x01, 0x37, 0x03, 0x39, 0x01, 0x3b, 0x03, 0x3c, 0x01, 274 | 0x3e, 0x03, 0x40, 0x03, 0x42, 0x03, 0x43, 0xff, 0x27, 0x47, 0xa7, 0xb1, 275 | 0x47, 0x17, 0x45, 0x03, 0x43, 0x03, 0x45, 0x01, 0x48, 0x01, 0x48, 0x03, 276 | 0x45, 0x01, 0x4a, 0x01, 0x4a, 0x03, 0x48, 0x27, 0x4c, 0xa7, 0xd1, 0x4c, 277 | 0x1f, 0x4a, 0x41, 0x01, 0x4c, 0x01, 0x4c, 0x01, 0x40, 0x01, 0x4d, 0x01, 278 | 0x40, 0x01, 0x48, 0x01, 0x4a, 0xff, 0x01, 0x4c, 0x01, 0x4c, 0x03, 0x40, 279 | 0x03, 0x4a, 0x01, 0x40, 0x03, 0x48, 0x01, 0x40, 0x03, 0x47, 0x01, 0x48, 280 | 0x01, 0x40, 0x01, 0x48, 0x01, 0x4a, 0xff, 0x01, 0x4c, 0x01, 0x4c, 0x03, 281 | 0x40, 0x03, 0x4b, 0x01, 0x40, 0x03, 0x49, 0x01, 0x40, 0x03, 0x47, 0x01, 282 | 0x49, 0x01, 0x40, 0x01, 0x49, 0x01, 0x4b, 0xff, 0x01, 0x49, 0x01, 0x49, 283 | 0x03, 0x3d, 0x03, 0x47, 0x01, 0x3d, 0x03, 0x46, 0x01, 0x3d, 0x03, 0x44, 284 | 0x01, 0x42, 0x01, 0x3d, 0x01, 0x47, 0x01, 0x49, 0xff, 0x87, 0x07, 0x68, 285 | 0x4f, 0x83, 0x0c, 0x2c, 0x03, 0x2c, 0xff, 0x85, 0x02, 0x15, 0x01, 0x21, 286 | 0x83, 0x03, 0x2e, 0x83, 0x02, 0x15, 0x07, 0x15, 0x83, 0x03, 0x2e, 0x81, 287 | 0x02, 0x1f, 0x01, 0x21, 0xff, 0x85, 0x02, 0x16, 0x01, 0x22, 0x83, 0x03, 288 | 0x2e, 0x83, 0x02, 0x16, 0x07, 0x16, 0x83, 0x03, 0x2e, 0x81, 0x02, 0x21, 289 | 0x01, 0x22, 0xff, 0x85, 0x02, 0x10, 0x01, 0x1c, 0x83, 0x03, 0x2e, 0x83, 290 | 0x02, 0x10, 0x07, 0x10, 0x83, 0x03, 0x2e, 0x81, 0x02, 0x1a, 0x01, 0x1c, 291 | 0xff, 0x85, 0x02, 0x18, 0x01, 0x24, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x18, 292 | 0x07, 0x18, 0x83, 0x03, 0x2e, 0x81, 0x02, 0x22, 0x01, 0x24, 0xff, 0x85, 293 | 0x02, 0x19, 0x01, 0x25, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x19, 0x07, 0x19, 294 | 0x83, 0x03, 0x2e, 0x81, 0x02, 0x24, 0x01, 0x25, 0xff, 0x85, 0x02, 0x13, 295 | 0x01, 0x1f, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x13, 0x07, 0x13, 0x83, 0x03, 296 | 0x2e, 0x81, 0x02, 0x1c, 0x01, 0x1c, 0xff, 0x85, 0x02, 0x1a, 0x01, 0x26, 297 | 0x83, 0x03, 0x2e, 0x83, 0x02, 0x1a, 0x07, 0x1a, 0x83, 0x03, 0x2e, 0x81, 298 | 0x02, 0x24, 0x01, 0x26, 0xff, 0x85, 0x02, 0x12, 0x01, 0x1e, 0x83, 0x03, 299 | 0x2e, 0x83, 0x02, 0x12, 0x07, 0x12, 0x83, 0x03, 0x2e, 0x81, 0x02, 0x1c, 300 | 0x01, 0x1e, 0xff, 0x85, 0x02, 0x19, 0x01, 0x25, 0x83, 0x03, 0x2e, 0x83, 301 | 0x02, 0x19, 0x07, 0x19, 0x83, 0x03, 0x2e, 0x81, 0x02, 0x23, 0x01, 0x25, 302 | 0xff, 0x87, 0x02, 0x15, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x15, 0x07, 0x15, 303 | 0x83, 0x03, 0x2e, 0x83, 0x02, 0x15, 0x07, 0x13, 0x83, 0x03, 0x2e, 0x83, 304 | 0x02, 0x13, 0x07, 0x13, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x13, 0x07, 0x1a, 305 | 0x83, 0x03, 0x2e, 0x83, 0x02, 0x1a, 0x07, 0x1a, 0x83, 0x03, 0x2e, 0x83, 306 | 0x02, 0x1a, 0x07, 0x1c, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x1c, 0x07, 0x1c, 307 | 0x83, 0x03, 0x2e, 0x83, 0x02, 0x1c, 0xff, 0x07, 0x1e, 0x83, 0x03, 0x2e, 308 | 0x83, 0x02, 0x1e, 0x07, 0x1e, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x1e, 0x07, 309 | 0x19, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x19, 0x07, 0x19, 0x83, 0x03, 0x2e, 310 | 0x83, 0x02, 0x19, 0xff, 0x07, 0x15, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x15, 311 | 0x07, 0x15, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x15, 0x07, 0x1a, 0x83, 0x03, 312 | 0x2e, 0x83, 0x02, 0x1a, 0x07, 0x1c, 0x83, 0x03, 0x2e, 0x83, 0x02, 0x1c, 313 | 0xff, 0x97, 0x08, 0x3d, 0x07, 0x3b, 0x03, 0x3e, 0x07, 0x3d, 0x07, 0x3b, 314 | 0x0b, 0x3d, 0x17, 0x39, 0x07, 0x39, 0xff, 0x03, 0x39, 0x07, 0x38, 0x0b, 315 | 0x36, 0x03, 0x38, 0x03, 0x39, 0xff, 0x03, 0x39, 0x07, 0x38, 0x07, 0x36, 316 | 0x0b, 0x34, 0xff, 0x17, 0x34, 0x03, 0x36, 0x03, 0x39, 0x07, 0x39, 0x0f, 317 | 0x38, 0x03, 0x39, 0x03, 0x3b, 0x07, 0x3d, 0x0f, 0x3b, 0x03, 0x3d, 0x03, 318 | 0x3e, 0x07, 0x3e, 0x07, 0x3d, 0x07, 0x3b, 0x07, 0x39, 0xff, 0x1f, 0x39, 319 | 0x43, 0x03, 0x32, 0x03, 0x34, 0x03, 0x32, 0x03, 0x39, 0x03, 0x38, 0x03, 320 | 0x34, 0x03, 0x3b, 0x1f, 0x39, 0x43, 0x03, 0x32, 0x03, 0x34, 0x03, 0x32, 321 | 0x03, 0x39, 0x03, 0x38, 0x03, 0x34, 0x03, 0x32, 0xff, 0x83, 0x09, 0x2d, 322 | 0x03, 0x34, 0x03, 0x39, 0x03, 0x34, 0x03, 0x39, 0x03, 0x39, 0x03, 0x34, 323 | 0x03, 0x39, 0xff, 0x81, 0x0a, 0x34, 0x01, 0x34, 0x03, 0x34, 0x03, 0x34, 324 | 0x03, 0x34, 0x07, 0x37, 0x07, 0x39, 0x01, 0x34, 0x01, 0x34, 0x03, 0x34, 325 | 0x03, 0x34, 0x03, 0x34, 0x07, 0x37, 0x07, 0x39, 0x41, 0x01, 0x3b, 0x03, 326 | 0x3b, 0x03, 0x3b, 0x03, 0x3d, 0x0f, 0x3b, 0xff, 0x81, 0x0a, 0x31, 0x01, 327 | 0x31, 0x03, 0x31, 0x03, 0x31, 0x03, 0x31, 0x07, 0x34, 0x07, 0x36, 0x01, 328 | 0x31, 0x01, 0x31, 0x03, 0x31, 0x03, 0x31, 0x03, 0x31, 0x07, 0x34, 0x07, 329 | 0x36, 0x41, 0x01, 0x38, 0x03, 0x38, 0x03, 0x38, 0x03, 0x3a, 0x0f, 0x38, 330 | 0xff, 0x81, 0x0a, 0x2d, 0x01, 0x2d, 0x03, 0x2d, 0x03, 0x2d, 0x03, 0x2d, 331 | 0x07, 0x30, 0x07, 0x32, 0x01, 0x2d, 0x01, 0x2d, 0x03, 0x2d, 0x03, 0x2d, 332 | 0x03, 0x2d, 0x07, 0x30, 0x07, 0x32, 0x41, 0x01, 0x34, 0x03, 0x34, 0x03, 333 | 0x34, 0x03, 0x36, 0x0f, 0x34, 0xff, 0xa0, 0x00, 0xaa, 0xbd, 0x14, 0x55, 334 | 0x8d, 0x17, 0x55, 0x8a, 0x0a, 0x8d, 0x04, 0x55, 0x0a, 0x18, 0x6d, 0x04, 335 | 0x55, 0xaa, 0xbd, 0xff, 0x56, 0x99, 0xf9, 0x56, 0xe8, 0xc8, 0xc0, 0x06, 336 | 0xd0, 0xf4, 0xa9, 0x00, 0x8d, 0x04, 0xd4, 0x8d, 0x0b, 0xd4, 0x8d, 0x12, 337 | 0xd4, 0xa9, 0x0f, 0x8d, 0x18, 0xd4, 0xa9, 0x40, 0x8d, 0x19, 0x55, 0x60, 338 | 0xa9, 0xc0, 0x8d, 0x19, 0x55, 0x60, 0xa9, 0x00, 0x8d, 0x26, 0x55, 0x60, 339 | 0xa9, 0xff, 0x8d, 0x26, 0x55, 0x4c, 0xcf, 0x53, 0xae, 0x26, 0x55, 0xf0, 340 | 0x04, 0x8e, 0x27, 0x55, 0x60, 0x09, 0x40, 0x8d, 0x27, 0x55, 0xa9, 0x0f, 341 | 0x8d, 0x18, 0xd4, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 342 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 343 | 0x00, 0x00, 0xc9, 0x03, 0xb0, 0x03, 0x4c, 0x00, 0x50, 0x48, 0x20, 0x42, 344 | 0x5f, 0x68, 0x38, 0xe9, 0x03, 0xaa, 0xbd, 0x98, 0x5f, 0x4c, 0x0f, 0x50, 345 | 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x05, 0x09, 0x0b, 0x0c 346 | }; 347 | unsigned int music_Commando_sid_len = 4126; 348 | -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | COMPONENT_ADD_INCLUDEDIRS := . 7 | 8 | CFLAGS += -Wno-error=sequence-point -Wno-error=parentheses -Wno-error=unused-value 9 | 10 | -------------------------------------------------------------------------------- /main/fonts.c: -------------------------------------------------------------------------------- 1 | #include "fonts.h" 2 | 3 | const uint16_t Font7x10 [] = { 4 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp 5 | 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ! 6 | 0x2800, 0x2800, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " 7 | 0x2400, 0x2400, 0x7C00, 0x2400, 0x4800, 0x7C00, 0x4800, 0x4800, 0x0000, 0x0000, // # 8 | 0x3800, 0x5400, 0x5000, 0x3800, 0x1400, 0x5400, 0x5400, 0x3800, 0x1000, 0x0000, // $ 9 | 0x2000, 0x5400, 0x5800, 0x3000, 0x2800, 0x5400, 0x1400, 0x0800, 0x0000, 0x0000, // % 10 | 0x1000, 0x2800, 0x2800, 0x1000, 0x3400, 0x4800, 0x4800, 0x3400, 0x0000, 0x0000, // & 11 | 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ' 12 | 0x0800, 0x1000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x1000, 0x0800, // ( 13 | 0x2000, 0x1000, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x1000, 0x2000, // ) 14 | 0x1000, 0x3800, 0x1000, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // * 15 | 0x0000, 0x0000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, // + 16 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // , 17 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3800, 0x0000, 0x0000, 0x0000, 0x0000, // - 18 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // . 19 | 0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x0000, 0x0000, // / 20 | 0x3800, 0x4400, 0x4400, 0x5400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 0 21 | 0x1000, 0x3000, 0x5000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // 1 22 | 0x3800, 0x4400, 0x4400, 0x0400, 0x0800, 0x1000, 0x2000, 0x7C00, 0x0000, 0x0000, // 2 23 | 0x3800, 0x4400, 0x0400, 0x1800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 3 24 | 0x0800, 0x1800, 0x2800, 0x2800, 0x4800, 0x7C00, 0x0800, 0x0800, 0x0000, 0x0000, // 4 25 | 0x7C00, 0x4000, 0x4000, 0x7800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 5 26 | 0x3800, 0x4400, 0x4000, 0x7800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 6 27 | 0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x2000, 0x2000, 0x0000, 0x0000, // 7 28 | 0x3800, 0x4400, 0x4400, 0x3800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 8 29 | 0x3800, 0x4400, 0x4400, 0x4400, 0x3C00, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 9 30 | 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // : 31 | 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // ; 32 | 0x0000, 0x0000, 0x0C00, 0x3000, 0x4000, 0x3000, 0x0C00, 0x0000, 0x0000, 0x0000, // < 33 | 0x0000, 0x0000, 0x0000, 0x7C00, 0x0000, 0x7C00, 0x0000, 0x0000, 0x0000, 0x0000, // = 34 | 0x0000, 0x0000, 0x6000, 0x1800, 0x0400, 0x1800, 0x6000, 0x0000, 0x0000, 0x0000, // > 35 | 0x3800, 0x4400, 0x0400, 0x0800, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ? 36 | 0x3800, 0x4400, 0x4C00, 0x5400, 0x5C00, 0x4000, 0x4000, 0x3800, 0x0000, 0x0000, // @ 37 | 0x1000, 0x2800, 0x2800, 0x2800, 0x2800, 0x7C00, 0x4400, 0x4400, 0x0000, 0x0000, // A 38 | 0x7800, 0x4400, 0x4400, 0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x0000, 0x0000, // B 39 | 0x3800, 0x4400, 0x4000, 0x4000, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // C 40 | 0x7000, 0x4800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4800, 0x7000, 0x0000, 0x0000, // D 41 | 0x7C00, 0x4000, 0x4000, 0x7C00, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // E 42 | 0x7C00, 0x4000, 0x4000, 0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // F 43 | 0x3800, 0x4400, 0x4000, 0x4000, 0x5C00, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // G 44 | 0x4400, 0x4400, 0x4400, 0x7C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // H 45 | 0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3800, 0x0000, 0x0000, // I 46 | 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // J 47 | 0x4400, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // K 48 | 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // L 49 | 0x4400, 0x6C00, 0x6C00, 0x5400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // M 50 | 0x4400, 0x6400, 0x6400, 0x5400, 0x5400, 0x4C00, 0x4C00, 0x4400, 0x0000, 0x0000, // N 51 | 0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // O 52 | 0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // P 53 | 0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x5400, 0x3800, 0x0400, 0x0000, // Q 54 | 0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // R 55 | 0x3800, 0x4400, 0x4000, 0x3000, 0x0800, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // S 56 | 0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // T 57 | 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // U 58 | 0x4400, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x1000, 0x0000, 0x0000, // V 59 | 0x4400, 0x4400, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // W 60 | 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, // X 61 | 0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // Y 62 | 0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // Z 63 | 0x1800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1800, // [ 64 | 0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x0000, 0x0000, /* \ */ 65 | 0x3000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3000, // ] 66 | 0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ 67 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE00, // _ 68 | 0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ` 69 | 0x0000, 0x0000, 0x3800, 0x4400, 0x3C00, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // a 70 | 0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x0000, 0x0000, // b 71 | 0x0000, 0x0000, 0x3800, 0x4400, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // c 72 | 0x0400, 0x0400, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // d 73 | 0x0000, 0x0000, 0x3800, 0x4400, 0x7C00, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // e 74 | 0x0C00, 0x1000, 0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // f 75 | 0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x7800, // g 76 | 0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // h 77 | 0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // i 78 | 0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0xE000, // j 79 | 0x4000, 0x4000, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4400, 0x0000, 0x0000, // k 80 | 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // l 81 | 0x0000, 0x0000, 0x7800, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x0000, 0x0000, // m 82 | 0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // n 83 | 0x0000, 0x0000, 0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // o 84 | 0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x4000, 0x4000, // p 85 | 0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x0400, // q 86 | 0x0000, 0x0000, 0x5800, 0x6400, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // r 87 | 0x0000, 0x0000, 0x3800, 0x4400, 0x3000, 0x0800, 0x4400, 0x3800, 0x0000, 0x0000, // s 88 | 0x2000, 0x2000, 0x7800, 0x2000, 0x2000, 0x2000, 0x2000, 0x1800, 0x0000, 0x0000, // t 89 | 0x0000, 0x0000, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // u 90 | 0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x0000, 0x0000, // v 91 | 0x0000, 0x0000, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // w 92 | 0x0000, 0x0000, 0x4400, 0x2800, 0x1000, 0x1000, 0x2800, 0x4400, 0x0000, 0x0000, // x 93 | 0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x6000, // y 94 | 0x0000, 0x0000, 0x7C00, 0x0800, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // z 95 | 0x1800, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1800, // { 96 | 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, // | 97 | 0x3000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x3000, // } 98 | 0x0000, 0x0000, 0x0000, 0x7400, 0x4C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ 99 | }; 100 | 101 | const uint16_t Font11x18 [] = { 102 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp 103 | 0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ! 104 | 0x0000, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " 105 | 0x0000, 0x1980, 0x1980, 0x1980, 0x1980, 0x7FC0, 0x7FC0, 0x1980, 0x3300, 0x7FC0, 0x7FC0, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, 0x0000, // # 106 | 0x0000, 0x1E00, 0x3F00, 0x7580, 0x6580, 0x7400, 0x3C00, 0x1E00, 0x0700, 0x0580, 0x6580, 0x6580, 0x7580, 0x3F00, 0x1E00, 0x0400, 0x0400, 0x0000, // $ 107 | 0x0000, 0x7000, 0xD800, 0xD840, 0xD8C0, 0xD980, 0x7300, 0x0600, 0x0C00, 0x1B80, 0x36C0, 0x66C0, 0x46C0, 0x06C0, 0x0380, 0x0000, 0x0000, 0x0000, // % 108 | 0x0000, 0x1E00, 0x3F00, 0x3300, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x3CC0, 0x66C0, 0x6380, 0x6180, 0x6380, 0x3EC0, 0x1C80, 0x0000, 0x0000, 0x0000, // & 109 | 0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ' 110 | 0x0080, 0x0100, 0x0300, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0300, 0x0100, 0x0080, // ( 111 | 0x2000, 0x1000, 0x1800, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x1800, 0x1000, 0x2000, // ) 112 | 0x0000, 0x0C00, 0x2D00, 0x3F00, 0x1E00, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // * 113 | 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // + 114 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // , 115 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x1E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // - 116 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // . 117 | 0x0000, 0x0300, 0x0300, 0x0300, 0x0600, 0x0600, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // / 118 | 0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6D80, 0x6D80, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 0 119 | 0x0000, 0x0600, 0x0E00, 0x1E00, 0x3600, 0x2600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 1 120 | 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // 2 121 | 0x0000, 0x1C00, 0x3E00, 0x6300, 0x6300, 0x0300, 0x0E00, 0x0E00, 0x0300, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 3 122 | 0x0000, 0x0600, 0x0E00, 0x0E00, 0x1E00, 0x1E00, 0x1600, 0x3600, 0x3600, 0x6600, 0x7F80, 0x7F80, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 4 123 | 0x0000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x6380, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 5 124 | 0x0000, 0x1E00, 0x3F00, 0x3380, 0x6180, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x3380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 6 125 | 0x0000, 0x7F80, 0x7F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0800, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // 7 126 | 0x0000, 0x1E00, 0x3F00, 0x6380, 0x6180, 0x6180, 0x2100, 0x1E00, 0x3F00, 0x6180, 0x6180, 0x6180, 0x6180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 8 127 | 0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6180, 0x7300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 9 128 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // : 129 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // ; 130 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0380, 0x0E00, 0x3800, 0x6000, 0x3800, 0x0E00, 0x0380, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // < 131 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // = 132 | 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x7000, 0x1C00, 0x0700, 0x0180, 0x0700, 0x1C00, 0x7000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // > 133 | 0x0000, 0x1F00, 0x3F80, 0x71C0, 0x60C0, 0x00C0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ? 134 | 0x0000, 0x1E00, 0x3F00, 0x3180, 0x7180, 0x6380, 0x6F80, 0x6D80, 0x6D80, 0x6F80, 0x6780, 0x6000, 0x3200, 0x3E00, 0x1C00, 0x0000, 0x0000, 0x0000, // @ 135 | 0x0000, 0x0E00, 0x0E00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x3180, 0x3180, 0x3F80, 0x3F80, 0x3180, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // A 136 | 0x0000, 0x7C00, 0x7E00, 0x6300, 0x6300, 0x6300, 0x6300, 0x7E00, 0x7E00, 0x6300, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x0000, 0x0000, 0x0000, // B 137 | 0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // C 138 | 0x0000, 0x7C00, 0x7F00, 0x6300, 0x6380, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6300, 0x6300, 0x7E00, 0x7C00, 0x0000, 0x0000, 0x0000, // D 139 | 0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // E 140 | 0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // F 141 | 0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6380, 0x6380, 0x6180, 0x6180, 0x3180, 0x3F80, 0x1E00, 0x0000, 0x0000, 0x0000, // G 142 | 0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7F80, 0x7F80, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // H 143 | 0x0000, 0x3F00, 0x3F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3F00, 0x3F00, 0x0000, 0x0000, 0x0000, // I 144 | 0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // J 145 | 0x0000, 0x60C0, 0x6180, 0x6300, 0x6600, 0x6600, 0x6C00, 0x7800, 0x7C00, 0x6600, 0x6600, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // K 146 | 0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // L 147 | 0x0000, 0x71C0, 0x71C0, 0x7BC0, 0x7AC0, 0x6AC0, 0x6AC0, 0x6EC0, 0x64C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // M 148 | 0x0000, 0x7180, 0x7180, 0x7980, 0x7980, 0x7980, 0x6D80, 0x6D80, 0x6D80, 0x6580, 0x6780, 0x6780, 0x6780, 0x6380, 0x6380, 0x0000, 0x0000, 0x0000, // N 149 | 0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // O 150 | 0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // P 151 | 0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6580, 0x6780, 0x3300, 0x3F80, 0x1E40, 0x0000, 0x0000, 0x0000, // Q 152 | 0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6600, 0x6300, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // R 153 | 0x0000, 0x0E00, 0x1F00, 0x3180, 0x3180, 0x3000, 0x3800, 0x1E00, 0x0700, 0x0380, 0x6180, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // S 154 | 0x0000, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // T 155 | 0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // U 156 | 0x0000, 0x60C0, 0x60C0, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x0400, 0x0000, 0x0000, 0x0000, // V 157 | 0x0000, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xCCC0, 0x4C80, 0x4C80, 0x5E80, 0x5280, 0x5280, 0x7380, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // W 158 | 0x0000, 0xC0C0, 0x6080, 0x6180, 0x3300, 0x3B00, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x1F00, 0x3B00, 0x7180, 0x6180, 0xC0C0, 0x0000, 0x0000, 0x0000, // X 159 | 0x0000, 0xC0C0, 0x6180, 0x6180, 0x3300, 0x3300, 0x1E00, 0x1E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // Y 160 | 0x0000, 0x3F80, 0x3F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // Z 161 | 0x0F00, 0x0F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0F00, 0x0F00, // [ 162 | 0x0000, 0x1800, 0x1800, 0x1800, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0300, 0x0300, 0x0300, 0x0000, 0x0000, 0x0000, /* \ */ 163 | 0x1E00, 0x1E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x1E00, 0x1E00, // ] 164 | 0x0000, 0x0C00, 0x0C00, 0x1E00, 0x1200, 0x3300, 0x3300, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ 165 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFE0, 0x0000, // _ 166 | 0x0000, 0x3800, 0x1800, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ` 167 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F00, 0x3F80, 0x6180, 0x0180, 0x1F80, 0x3F80, 0x6180, 0x6380, 0x7F80, 0x38C0, 0x0000, 0x0000, 0x0000, // a 168 | 0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x0000, 0x0000, 0x0000, // b 169 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6000, 0x6000, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // c 170 | 0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0000, 0x0000, 0x0000, // d 171 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x7F80, 0x7F80, 0x6000, 0x7180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // e 172 | 0x0000, 0x07C0, 0x0FC0, 0x0C00, 0x0C00, 0x7F80, 0x7F80, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // f 173 | 0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6380, 0x7F00, 0x3E00, // g 174 | 0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // h 175 | 0x0000, 0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // i 176 | 0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x4600, 0x7E00, 0x3C00, // j 177 | 0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x6300, 0x6600, 0x6C00, 0x7C00, 0x7600, 0x6300, 0x6300, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // k 178 | 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // l 179 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xFFC0, 0xCEC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0x0000, 0x0000, 0x0000, // m 180 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // n 181 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // o 182 | 0x0000, 0x0000, 0x0000, 0x0000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x6000, 0x6000, 0x6000, 0x6000, // p 183 | 0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x0180, 0x0180, 0x0180, // q 184 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6700, 0x3F80, 0x3900, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, // r 185 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F80, 0x6180, 0x6000, 0x7F00, 0x3F80, 0x0180, 0x6180, 0x7F00, 0x1E00, 0x0000, 0x0000, 0x0000, // s 186 | 0x0000, 0x0000, 0x0800, 0x1800, 0x1800, 0x7F00, 0x7F00, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1F80, 0x0F80, 0x0000, 0x0000, 0x0000, // t 187 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F80, 0x3D80, 0x0000, 0x0000, 0x0000, // u 188 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0600, 0x0000, 0x0000, 0x0000, // v 189 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xDD80, 0xDD80, 0x5500, 0x5500, 0x5500, 0x7700, 0x7700, 0x2200, 0x2200, 0x0000, 0x0000, 0x0000, // w 190 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x3300, 0x3300, 0x6180, 0x0000, 0x0000, 0x0000, // x 191 | 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x3180, 0x3300, 0x3300, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x1C00, 0x7C00, 0x7000, // y 192 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FC0, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x7FC0, 0x7FC0, 0x0000, 0x0000, 0x0000, // z 193 | 0x0380, 0x0780, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0E00, 0x1C00, 0x1C00, 0x0E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0780, 0x0380, // { 194 | 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, // | 195 | 0x3800, 0x3C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0E00, 0x0700, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3C00, 0x3800, // } 196 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3880, 0x7F80, 0x4700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ 197 | }; 198 | 199 | const uint16_t Font16x26 [] = { 200 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [ ] 201 | 0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x03C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [!] 202 | 0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ["] 203 | 0x01CE,0x03CE,0x03DE,0x039E,0x039C,0x079C,0x3FFF,0x7FFF,0x0738,0x0F38,0x0F78,0x0F78,0x0E78,0xFFFF,0xFFFF,0x1EF0,0x1CF0,0x1CE0,0x3CE0,0x3DE0,0x39E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [#] 204 | 0x03FC,0x0FFE,0x1FEE,0x1EE0,0x1EE0,0x1EE0,0x1EE0,0x1FE0,0x0FE0,0x07E0,0x03F0,0x01FC,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x3DFE,0x3FFC,0x0FF0,0x01E0,0x01E0,0x0000,0x0000,0x0000, // Ascii = [$] 205 | 0x3E03,0xF707,0xE78F,0xE78E,0xE39E,0xE3BC,0xE7B8,0xE7F8,0xF7F0,0x3FE0,0x01C0,0x03FF,0x07FF,0x07F3,0x0FF3,0x1EF3,0x3CF3,0x38F3,0x78F3,0xF07F,0xE03F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [%] 206 | 0x07E0,0x0FF8,0x0F78,0x1F78,0x1F78,0x1F78,0x0F78,0x0FF0,0x0FE0,0x1F80,0x7FC3,0xFBC3,0xF3E7,0xF1F7,0xF0F7,0xF0FF,0xF07F,0xF83E,0x7C7F,0x3FFF,0x1FEF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [&] 207 | 0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ['] 208 | 0x003F,0x007C,0x01F0,0x01E0,0x03C0,0x07C0,0x0780,0x0780,0x0F80,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F80,0x0780,0x0780,0x07C0,0x03C0,0x01E0,0x01F0,0x007C,0x003F,0x000F,0x0000, // Ascii = [(] 209 | 0x7E00,0x1F00,0x07C0,0x03C0,0x01E0,0x01F0,0x00F0,0x00F0,0x00F8,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x00F8,0x00F0,0x00F0,0x01F0,0x01E0,0x03C0,0x07C0,0x1F00,0x7E00,0x7800,0x0000, // Ascii = [)] 210 | 0x03E0,0x03C0,0x01C0,0x39CE,0x3FFF,0x3F7F,0x0320,0x0370,0x07F8,0x0F78,0x1F3C,0x0638,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [*] 211 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0xFFFF,0xFFFF,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [+] 212 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x01C0,0x0380, // Ascii = [,] 213 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [-] 214 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [.] 215 | 0x000F,0x000F,0x001E,0x001E,0x003C,0x003C,0x0078,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0780,0x0F00,0x0F00,0x1E00,0x1E00,0x3C00,0x3C00,0x7800,0x7800,0xF000,0x0000, // Ascii = [/] 216 | 0x07F0,0x0FF8,0x1F7C,0x3E3E,0x3C1E,0x7C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x7C1F,0x3C1E,0x3E3E,0x1F7C,0x0FF8,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [0] 217 | 0x00F0,0x07F0,0x3FF0,0x3FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [1] 218 | 0x0FE0,0x3FF8,0x3C7C,0x003C,0x003E,0x003E,0x003E,0x003C,0x003C,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0780,0x0F00,0x1E00,0x3E00,0x3C00,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [2] 219 | 0x0FF0,0x1FF8,0x1C7C,0x003E,0x003E,0x003E,0x003C,0x003C,0x00F8,0x0FF0,0x0FF8,0x007C,0x003E,0x001E,0x001E,0x001E,0x001E,0x003E,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [3] 220 | 0x0078,0x00F8,0x00F8,0x01F8,0x03F8,0x07F8,0x07F8,0x0F78,0x1E78,0x1E78,0x3C78,0x7878,0x7878,0xFFFF,0xFFFF,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [4] 221 | 0x1FFC,0x1FFC,0x1FFC,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FE0,0x1FF8,0x00FC,0x007C,0x003E,0x003E,0x001E,0x003E,0x003E,0x003C,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [5] 222 | 0x01FC,0x07FE,0x0F8E,0x1F00,0x1E00,0x3E00,0x3C00,0x3C00,0x3DF8,0x3FFC,0x7F3E,0x7E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3E0F,0x1E1F,0x1F3E,0x0FFC,0x03F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [6] 223 | 0x3FFF,0x3FFF,0x3FFF,0x000F,0x001E,0x001E,0x003C,0x0038,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0F80,0x0F80,0x0F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [7] 224 | 0x07F8,0x0FFC,0x1F3E,0x1E1E,0x3E1E,0x3E1E,0x1E1E,0x1F3C,0x0FF8,0x07F0,0x0FF8,0x1EFC,0x3E3E,0x3C1F,0x7C1F,0x7C0F,0x7C0F,0x3C1F,0x3F3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [8] 225 | 0x07F0,0x0FF8,0x1E7C,0x3C3E,0x3C1E,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x3C1F,0x3E3F,0x1FFF,0x07EF,0x001F,0x001E,0x001E,0x003E,0x003C,0x38F8,0x3FF0,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [9] 226 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [:] 227 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x03C0,0x0380, // Ascii = [;] 228 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0x000F,0x003F,0x00FC,0x03F0,0x0FC0,0x3F00,0xFE00,0x3F00,0x0FC0,0x03F0,0x00FC,0x003F,0x000F,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [<] 229 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [=] 230 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xE000,0xF800,0x7E00,0x1F80,0x07E0,0x01F8,0x007E,0x001F,0x007E,0x01F8,0x07E0,0x1F80,0x7E00,0xF800,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [>] 231 | 0x1FF0,0x3FFC,0x383E,0x381F,0x381F,0x001E,0x001E,0x003C,0x0078,0x00F0,0x01E0,0x03C0,0x03C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [?] 232 | 0x03F8,0x0FFE,0x1F1E,0x3E0F,0x3C7F,0x78FF,0x79EF,0x73C7,0xF3C7,0xF38F,0xF38F,0xF38F,0xF39F,0xF39F,0x73FF,0x7BFF,0x79F7,0x3C00,0x1F1C,0x0FFC,0x03F8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [@] 233 | 0x0000,0x0000,0x0000,0x03E0,0x03E0,0x07F0,0x07F0,0x07F0,0x0F78,0x0F78,0x0E7C,0x1E3C,0x1E3C,0x3C3E,0x3FFE,0x3FFF,0x781F,0x780F,0xF00F,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [A] 234 | 0x0000,0x0000,0x0000,0x3FF8,0x3FFC,0x3C3E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7C,0x3FF0,0x3FF8,0x3C7E,0x3C1F,0x3C1F,0x3C0F,0x3C0F,0x3C1F,0x3FFE,0x3FF8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [B] 235 | 0x0000,0x0000,0x0000,0x01FF,0x07FF,0x1F87,0x3E00,0x3C00,0x7C00,0x7800,0x7800,0x7800,0x7800,0x7800,0x7C00,0x7C00,0x3E00,0x3F00,0x1F83,0x07FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [C] 236 | 0x0000,0x0000,0x0000,0x7FF0,0x7FFC,0x787E,0x781F,0x781F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x781F,0x781E,0x787E,0x7FF8,0x7FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [D] 237 | 0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFE,0x3FFE,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [E] 238 | 0x0000,0x0000,0x0000,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [F] 239 | 0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x7C00,0x7C00,0x7800,0xF800,0xF800,0xF87F,0xF87F,0x780F,0x7C0F,0x7C0F,0x3E0F,0x1F8F,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [G] 240 | 0x0000,0x0000,0x0000,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7FFF,0x7FFF,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [H] 241 | 0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [I] 242 | 0x0000,0x0000,0x0000,0x1FFC,0x1FFC,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x0078,0x0078,0x38F8,0x3FF0,0x3FC0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [J] 243 | 0x0000,0x0000,0x0000,0x3C1F,0x3C1E,0x3C3C,0x3C78,0x3CF0,0x3DE0,0x3FE0,0x3FC0,0x3F80,0x3FC0,0x3FE0,0x3DF0,0x3CF0,0x3C78,0x3C7C,0x3C3E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [K] 244 | 0x0000,0x0000,0x0000,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [L] 245 | 0x0000,0x0000,0x0000,0xF81F,0xFC1F,0xFC1F,0xFE3F,0xFE3F,0xFE3F,0xFF7F,0xFF77,0xFF77,0xF7F7,0xF7E7,0xF3E7,0xF3E7,0xF3C7,0xF007,0xF007,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [M] 246 | 0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7E0F,0x7F0F,0x7F0F,0x7F8F,0x7F8F,0x7FCF,0x7BEF,0x79EF,0x79FF,0x78FF,0x78FF,0x787F,0x783F,0x783F,0x781F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [N] 247 | 0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [O] 248 | 0x0000,0x0000,0x0000,0x3FFC,0x3FFF,0x3E1F,0x3E0F,0x3E0F,0x3E0F,0x3E0F,0x3E1F,0x3E3F,0x3FFC,0x3FF0,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [P] 249 | 0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F8,0x007C,0x003F,0x000F,0x0003,0x0000, // Ascii = [Q] 250 | 0x0000,0x0000,0x0000,0x3FF0,0x3FFC,0x3C7E,0x3C3E,0x3C1E,0x3C1E,0x3C3E,0x3C3C,0x3CFC,0x3FF0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [R] 251 | 0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x3E0E,0x3C00,0x3C00,0x3C00,0x3E00,0x1FC0,0x0FF8,0x03FE,0x007F,0x001F,0x000F,0x000F,0x201F,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [S] 252 | 0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [T] 253 | 0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x3C1E,0x3C1E,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [U] 254 | 0x0000,0x0000,0x0000,0xF007,0xF007,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1F3C,0x1F78,0x0F78,0x0FF8,0x07F0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [V] 255 | 0x0000,0x0000,0x0000,0xE003,0xF003,0xF003,0xF007,0xF3E7,0xF3E7,0xF3E7,0x73E7,0x7BF7,0x7FF7,0x7FFF,0x7F7F,0x7F7F,0x7F7E,0x3F7E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [W] 256 | 0x0000,0x0000,0x0000,0xF807,0x7C0F,0x3E1E,0x3E3E,0x1F3C,0x0FF8,0x07F0,0x07E0,0x03E0,0x03E0,0x07F0,0x0FF8,0x0F7C,0x1E7C,0x3C3E,0x781F,0x780F,0xF00F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [X] 257 | 0x0000,0x0000,0x0000,0xF807,0x7807,0x7C0F,0x3C1E,0x3E1E,0x1F3C,0x0F78,0x0FF8,0x07F0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Y] 258 | 0x0000,0x0000,0x0000,0x7FFF,0x7FFF,0x000F,0x001F,0x003E,0x007C,0x00F8,0x00F0,0x01E0,0x03E0,0x07C0,0x0F80,0x0F00,0x1E00,0x3E00,0x7C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Z] 259 | 0x07FF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07FF,0x07FF,0x0000, // Ascii = [[] 260 | 0x7800,0x7800,0x3C00,0x3C00,0x1E00,0x1E00,0x0F00,0x0F00,0x0780,0x0780,0x03C0,0x03C0,0x01E0,0x01E0,0x00F0,0x00F0,0x0078,0x0078,0x003C,0x003C,0x001E,0x001E,0x000F,0x000F,0x0007,0x0000, // Ascii = [\] 261 | 0x7FF0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x7FF0,0x7FF0,0x0000, // Ascii = []] 262 | 0x00C0,0x01C0,0x01C0,0x03E0,0x03E0,0x07F0,0x07F0,0x0778,0x0F78,0x0F38,0x1E3C,0x1E3C,0x3C1E,0x3C1E,0x380F,0x780F,0x7807,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [^] 263 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000, // Ascii = [_] 264 | 0x00F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [`] 265 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FF8,0x3FFC,0x3C7C,0x003E,0x003E,0x003E,0x07FE,0x1FFE,0x3E3E,0x7C3E,0x783E,0x7C3E,0x7C7E,0x3FFF,0x1FCF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [a] 266 | 0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3C1E,0x3F3E,0x3FFC,0x3BF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [b] 267 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x3E00,0x3C00,0x7C00,0x7C00,0x7C00,0x3C00,0x3E00,0x3E00,0x1F87,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [c] 268 | 0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,0x07FF,0x1FFF,0x3E3F,0x3C1F,0x7C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [d] 269 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03F8,0x0FFC,0x1F3E,0x3E1E,0x3C1F,0x7C1F,0x7FFF,0x7FFF,0x7C00,0x7C00,0x3C00,0x3E00,0x1F07,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [e] 270 | 0x01FF,0x03E1,0x03C0,0x07C0,0x07C0,0x07C0,0x7FFF,0x7FFF,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [f] 271 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EF,0x1FFF,0x3E7F,0x3C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x001E,0x001E,0x001E,0x387C,0x3FF8, // Ascii = [g] 272 | 0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [h] 273 | 0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x7FE0,0x7FE0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [i] 274 | 0x00F8,0x00F8,0x0000,0x0000,0x0000,0x0000,0x3FF8,0x3FF8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F0,0x71F0,0x7FE0, // Ascii = [j] 275 | 0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C1F,0x3C3E,0x3C7C,0x3CF8,0x3DF0,0x3DE0,0x3FC0,0x3FC0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [k] 276 | 0x7FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [l] 277 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF79E,0xFFFF,0xFFFF,0xFFFF,0xFBE7,0xF9E7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [m] 278 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [n] 279 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x3C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x3C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [o] 280 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3E1E,0x3F3E,0x3FFC,0x3FF8,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00, // Ascii = [p] 281 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EE,0x1FFE,0x3E7E,0x3C1E,0x7C1E,0x781E,0x781E,0x781E,0x781E,0x781E,0x7C1E,0x7C3E,0x3E7E,0x1FFE,0x0FDE,0x001E,0x001E,0x001E,0x001E,0x001E, // Ascii = [q] 282 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1F7F,0x1FFF,0x1FE7,0x1FC7,0x1F87,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [r] 283 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x1E0E,0x3E00,0x3E00,0x3F00,0x1FE0,0x07FC,0x00FE,0x003E,0x001E,0x001E,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [s] 284 | 0x0000,0x0000,0x0000,0x0780,0x0780,0x0780,0x7FFF,0x7FFF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07C0,0x03FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [t] 285 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7E,0x3EFE,0x1FFE,0x0FDE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [u] 286 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF007,0x780F,0x780F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1E3C,0x0F78,0x0F78,0x0FF0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [v] 287 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF003,0xF1E3,0xF3E3,0xF3E7,0xF3F7,0xF3F7,0x7FF7,0x7F77,0x7F7F,0x7F7F,0x7F7F,0x3E3E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [w] 288 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7C0F,0x3E1E,0x3E3C,0x1F3C,0x0FF8,0x07F0,0x07F0,0x03E0,0x07F0,0x07F8,0x0FF8,0x1E7C,0x3E3E,0x3C1F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [x] 289 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x1E3C,0x1E3C,0x1F3C,0x0F78,0x0FF8,0x07F0,0x07F0,0x03E0,0x03E0,0x03C0,0x03C0,0x03C0,0x0780,0x0F80,0x7F00, // Ascii = [y] 290 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x001F,0x003E,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0F80,0x1F00,0x1E00,0x3C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [z] 291 | 0x01FE,0x03E0,0x03C0,0x03C0,0x03C0,0x03C0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x3F80,0x3F80,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x03C0,0x03C0,0x03C0,0x03C0,0x03E0,0x01FE,0x007E,0x0000, // Ascii = [{] 292 | 0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000, // Ascii = [|] 293 | 0x3FC0,0x03E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x00FE,0x00FE,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x01E0,0x03E0,0x3FC0,0x3F00,0x0000, // Ascii = [}] 294 | 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3F07,0x7FC7,0x73E7,0xF1FF,0xF07E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [~] 295 | }; 296 | 297 | 298 | FontDef_t Font_7x10 = { 299 | 7, 300 | 10, 301 | Font7x10 302 | }; 303 | 304 | FontDef_t Font_11x18 = { 305 | 11, 306 | 18, 307 | Font11x18 308 | }; 309 | 310 | FontDef_t Font_16x26 = { 311 | 16, 312 | 26, 313 | Font16x26 314 | }; 315 | 316 | char* Font_GetStringSize(char* str, FontSize_t* SizeStruct, FontDef_t* Font) { 317 | /* Fill settings */ 318 | SizeStruct->Height = Font->FontHeight; 319 | SizeStruct->Length = Font->FontWidth * strlen(str); 320 | 321 | /* Return pointer */ 322 | return str; 323 | } 324 | -------------------------------------------------------------------------------- /main/fonts.h: -------------------------------------------------------------------------------- 1 | #ifndef FONTS_H 2 | #define FONTS_H 3 | 4 | #include "string.h" 5 | #include 6 | #include "esp_system.h" 7 | 8 | typedef struct { 9 | uint8_t FontWidth; /*!< Font width in pixels */ 10 | uint8_t FontHeight; /*!< Font height in pixels */ 11 | const uint16_t *data; /*!< Pointer to data font data array */ 12 | } FontDef_t; 13 | 14 | /** 15 | * @brief String length and height 16 | */ 17 | typedef struct { 18 | uint16_t Length; /*!< String length in units of pixels */ 19 | uint16_t Height; /*!< String height in units of pixels */ 20 | } FontSize_t; 21 | 22 | /** 23 | * @brief 7 x 10 pixels font size structure 24 | */ 25 | extern FontDef_t Font_7x10; 26 | 27 | /** 28 | * @brief 11 x 18 pixels font size structure 29 | */ 30 | extern FontDef_t Font_11x18; 31 | 32 | /** 33 | * @brief 16 x 26 pixels font size structure 34 | */ 35 | extern FontDef_t Font_16x26; 36 | 37 | /** 38 | * @brief Calculates string length and height in units of pixels depending on string and font used 39 | * @param *str: String to be checked for length and height 40 | * @param *SizeStruct: Pointer to empty @ref TM_FONTS_SIZE_t structure where informations will be saved 41 | * @param *Font: Pointer to @ref TM_FontDef_t font used for calculations 42 | * @retval Pointer to string used for length and height 43 | */ 44 | char* Font_GetStringSize(char* str, FontSize_t* SizeStruct, FontDef_t* Font); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /main/libcsid.h: -------------------------------------------------------------------------------- 1 | #ifndef _CSID_H_ 2 | #define _CSID_H_ 3 | 4 | #define MAX_DATA_LEN 65536 5 | 6 | #define SIDMODEL_8580 8580 7 | #define SIDMODEL_6581 6581 8 | 9 | #define DEFAULT_SAMPLERATE 44100 10 | #define DEFAULT_SIDMODEL SIDMODEL_6581 11 | 12 | extern void libcsid_init(int samplerate, int sidmodel); 13 | 14 | extern int libcsid_load(unsigned char *buffer, int bufferlen, int subtune); 15 | 16 | extern const char *libcsid_getauthor(); 17 | extern const char *libcsid_getinfo(); 18 | extern const char *libcsid_gettitle(); 19 | 20 | extern void libcsid_render(unsigned short *output, int numsamples); 21 | 22 | #endif -------------------------------------------------------------------------------- /main/libcsidlight.c: -------------------------------------------------------------------------------- 1 | // Based of cSID light - an attempt at a usable simple API 2 | 3 | // cSID by Hermit (Mihaly Horvath), (Year 2017) http://hermit.sidrip.com 4 | // (based on jsSID, this version has much lower CPU-usage, as mainloop runs at samplerate) 5 | // License: WTF - Do what the fuck you want with this code, but please mention me as its original author. 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | typedef unsigned char byte; 15 | typedef unsigned char Uint8; 16 | 17 | //global constants and variables 18 | #define C64_PAL_CPUCLK 985248.0 19 | #define SID_CHANNEL_AMOUNT 3 20 | #define MAX_FILENAME_LEN 512 21 | #define MAX_DATA_LEN 65536 22 | #define PAL_FRAMERATE 50.06 //50.0443427 //50.1245419 //(C64_PAL_CPUCLK/63/312.5), selected carefully otherwise some ADSR-sensitive tunes may suffer more: 23 | #define DEFAULT_SAMPLERATE 44100.0 //(Soldier of Fortune, 2nd Reality, Alliance, X-tra energy, Jackal, Sanxion, Ultravox, Hard Track, Swing, Myth, LN3, etc.) 24 | #define CLOCK_RATIO_DEFAULT C64_PAL_CPUCLK/DEFAULT_SAMPLERATE //(50.0567520: lowest framerate where Sanxion is fine, and highest where Myth is almost fine) 25 | #define VCR_SHUNT_6581 1500 //kOhm //cca 1.5 MOhm Rshunt across VCR FET drain and source (causing 220Hz bottom cutoff with 470pF integrator capacitors in old C64) 26 | #define VCR_FET_TRESHOLD 192 //Vth (on cutoff numeric range 0..2048) for the VCR cutoff-frequency control FET below which it doesn't conduct 27 | #define CAP_6581 0.470 //nF //filter capacitor value for 6581 28 | #define FILTER_DARKNESS_6581 22.0 //the bigger the value, the darker the filter control is (that is, cutoff frequency increases less with the same cutoff-value) 29 | #define FILTER_DISTORTION_6581 0.0016 //the bigger the value the more of resistance-modulation (filter distortion) is applied for 6581 cutoff-control 30 | 31 | int OUTPUT_SCALEDOWN = SID_CHANNEL_AMOUNT * 16 + 26; 32 | // //raw output divided by this after multiplied by main volume, this also compensates for filter-resonance emphasis to avoid distotion 33 | 34 | enum { GATE_BITMASK=0x01, SYNC_BITMASK=0x02, RING_BITMASK=0x04, TEST_BITMASK=0x08, 35 | TRI_BITMASK=0x10, SAW_BITMASK=0x20, PULSE_BITMASK=0x40, NOISE_BITMASK=0x80, 36 | HOLDZERO_BITMASK=0x10, DECAYSUSTAIN_BITMASK=0x40, ATTACK_BITMASK=0x80, 37 | LOWPASS_BITMASK=0x10, BANDPASS_BITMASK=0x20, HIGHPASS_BITMASK=0x40, OFF3_BITMASK=0x80 }; 38 | 39 | float clock_ratio=CLOCK_RATIO_DEFAULT; 40 | 41 | //SID-emulation variables: 42 | const byte FILTSW[9] = {1,2,4,1,2,4,1,2,4}; 43 | byte ADSRstate[9], expcnt[9], prevSR[9], sourceMSBrise[9]; 44 | short int envcnt[9]; 45 | unsigned int prevwfout[9], prevwavdata[9], sourceMSB[3], noise_LFSR[9]; 46 | int phaseaccu[9], prevaccu[9], prevlowpass[3], prevbandpass[3];; 47 | float ratecnt[9], cutoff_ratio_8580, cutoff_steepness_6581, cap_6581_reciprocal; //, cutoff_ratio_6581, cutoff_bottom_6581, cutoff_top_6581; 48 | //player-related variables: 49 | int SIDamount=1, SID_model[3]={8580,8580,8580}, requested_SID_model=-1, sampleratio; 50 | byte *filedata, *memory, timermode[0x20], SIDtitle[0x20], SIDauthor[0x20], SIDinfo[0x20]; 51 | int subtune=0, tunelength=-1, default_tunelength=300, minutes=-1, seconds=-1; 52 | unsigned int initaddr, playaddr, playaddf, SID_address[3]={0xD400,0,0}; 53 | int samplerate = DEFAULT_SAMPLERATE; 54 | float framecnt=0, frame_sampleperiod = DEFAULT_SAMPLERATE/PAL_FRAMERATE; 55 | //CPU (and CIA/VIC-IRQ) emulation constants and variables - avoiding internal/automatic variables to retain speed 56 | const byte flagsw[]={0x01,0x21,0x04,0x24,0x00,0x40,0x08,0x28}, branchflag[]={0x80,0x40,0x01,0x02}; 57 | unsigned int PC=0, pPC=0, addr=0, storadd=0; 58 | short int A=0, T=0, SP=0xFF; 59 | byte X=0, Y=0, IR=0, ST=0x00; //STATUS-flags: N V - B D I Z C 60 | float CPUtime=0.0; 61 | unsigned char cycles=0, finished=0, dynCIA=0; 62 | 63 | //function prototypes 64 | void cSID_init(int samplerate); 65 | int SID(unsigned char num, unsigned int baseaddr); 66 | void initSID(); 67 | void initCPU (unsigned int mempos); 68 | byte CPU (); 69 | void init (byte subtune); void play(void* userdata, Uint8 *stream, int len ); 70 | unsigned int combinedWF(unsigned char num, unsigned char channel, unsigned int* wfarray, int index, unsigned char differ6581, byte freq); 71 | void createCombinedWF(unsigned int* wfarray, float bitmul, float bitstrength, float treshold); 72 | 73 | 74 | 75 | //----------------------------- MAIN thread ---------------------------- 76 | 77 | 78 | void init (byte subt) 79 | { 80 | static int timeout; subtune = subt; initCPU(initaddr); initSID(); A=subtune; memory[1]=0x37; memory[0xDC05]=0; 81 | for(timeout=100000;timeout>=0;timeout--) { if (CPU()) break; } 82 | if (timermode[subtune] || memory[0xDC05]) { //&& playaddf { //CIA timing 83 | if (!memory[0xDC05]) {memory[0xDC04]=0x24; memory[0xDC05]=0x40;} //C64 startup-default 84 | frame_sampleperiod = (memory[0xDC04]+memory[0xDC05]*256)/clock_ratio; } 85 | else frame_sampleperiod = samplerate/PAL_FRAMERATE; //Vsync timing 86 | printf("Frame-sampleperiod: %.0f samples (%.1fX speed)\n", round(frame_sampleperiod), samplerate/PAL_FRAMERATE/frame_sampleperiod); 87 | //frame_sampleperiod = (memory[0xDC05]!=0 || (!timermode[subtune] && playaddf))? samplerate/PAL_FRAMERATE : (memory[0xDC04] + memory[0xDC05]*256) / clock_ratio; 88 | if(playaddf==0) { playaddr = ((memory[1]&3)<2)? memory[0xFFFE]+memory[0xFFFF]*256 : memory[0x314]+memory[0x315]*256; printf("IRQ-playaddress:%4.4X\n",playaddr); } 89 | else { playaddr=playaddf; if (playaddr>=0xE000 && memory[1]==0x37) memory[1]=0x35; } //player under KERNAL (Crystal Kingdom Dizzy) 90 | initCPU(playaddr); framecnt=1; finished=0; CPUtime=0; 91 | } 92 | 93 | 94 | void play(void* userdata, Uint8 *stream, int len ) //called by SDL at samplerate pace 95 | { 96 | static int i,j, output; 97 | for(i=0;i=0xFE || ( (memory[1]&3)>1 && pPC<0xE000 && (PC==0xEA31 || PC==0xEA81) ) ) {finished=1;break;} else CPUtime+=cycles; //RTS,RTI and IRQ player ROM return handling 102 | if ( (addr==0xDC05 || addr==0xDC04) && (memory[1]&3) && timermode[subtune] ) { 103 | frame_sampleperiod = (memory[0xDC04] + memory[0xDC05]*256) / clock_ratio; //dynamic CIA-setting (Galway/Rubicon workaround) 104 | if (!dynCIA) {dynCIA=1; printf("( Dynamic CIA settings. New frame-sampleperiod: %.0f samples (%.1fX speed) )\n", round(frame_sampleperiod), samplerate/PAL_FRAMERATE/frame_sampleperiod);} 105 | } 106 | if(storadd>=0xD420 && storadd<0xD800 && (memory[1]&3)) { //CJ in the USA workaround (writing above $d420, except SID2/SID3) 107 | if ( !(SID_address[1]<=storadd && storadd=2) output += SID(1,SID_address[1]); 118 | if (SIDamount==3) output += SID(2,SID_address[2]); 119 | stream[i]=output&0xFF; stream[i+1]=output>>8; 120 | } 121 | } 122 | 123 | 124 | 125 | // //--------------------------------- CPU emulation ------------------------------------------- 126 | 127 | 128 | void initCPU (unsigned int mempos) { 129 | PC = mempos; 130 | A = 0; 131 | X = 0; 132 | Y = 0; 133 | ST = 0; 134 | SP = 0xFF; 135 | } 136 | 137 | //My CPU implementation is based on the instruction table by Graham at codebase64. 138 | //After some examination of the table it was clearly seen that columns of the table (instructions' 2nd nybbles) 139 | // mainly correspond to addressing modes, and double-rows usually have the same instructions. 140 | //The code below is laid out like this, with some exceptions present. 141 | //Thanks to the hardware being in my mind when coding this, the illegal instructions could be added fairly easily... 142 | byte CPU () //the CPU emulation for SID/PRG playback (ToDo: CIA/VIC-IRQ/NMI/RESET vectors, BCD-mode) 143 | { //'IR' is the instruction-register, naming after the hardware-equivalent 144 | IR=memory[PC]; cycles=2; storadd=0; //'cycle': ensure smallest 6510 runtime (for implied/register instructions) 145 | if(IR&1) { //nybble2: 1/5/9/D:accu.instructions, 3/7/B/F:illegal opcodes 146 | switch (IR&0x1F) { //addressing modes (begin with more complex cases), PC wraparound not handled inside to save codespace 147 | case 1: case 3: PC++; addr = memory[memory[PC]+X] + memory[memory[PC]+X+1]*256; cycles=6; break; //(zp,x) 148 | case 0x11: case 0x13: PC++; addr = memory[memory[PC]] + memory[memory[PC]+1]*256 + Y; cycles=6; break; //(zp),y (5..6 cycles, 8 for R-M-W) 149 | case 0x19: case 0x1B: PC++; addr=memory[PC]; PC++; addr+=memory[PC]*256 + Y; cycles=5; break; //abs,y //(4..5 cycles, 7 cycles for R-M-W) 150 | case 0x1D: PC++; addr=memory[PC]; PC++; addr+=memory[PC]*256 + X; cycles=5; break; //abs,x //(4..5 cycles, 7 cycles for R-M-W) 151 | case 0xD: case 0xF: PC++; addr=memory[PC]; PC++; addr+=memory[PC]*256; cycles=4; break; //abs 152 | case 0x15: PC++; addr = memory[PC] + X; cycles=4; break; //zp,x 153 | case 5: case 7: PC++; addr = memory[PC]; cycles=3; break; //zp 154 | case 0x17: PC++; if ((IR&0xC0)!=0x80) { addr = memory[PC] + X; cycles=4; } //zp,x for illegal opcodes 155 | else { addr = memory[PC] + Y; cycles=4; } break; //zp,y for LAX/SAX illegal opcodes 156 | case 0x1F: PC++; if ((IR&0xC0)!=0x80) { addr = memory[PC] + memory[++PC]*256 + X; cycles=5; } //abs,x for illegal opcodes 157 | else { addr = memory[PC] + memory[++PC]*256 + Y; cycles=5; } break; //abs,y for LAX/SAX illegal opcodes 158 | case 9: case 0xB: PC++; addr = PC; cycles=2; //immediate 159 | } 160 | addr&=0xFFFF; 161 | switch (IR&0xE0) { 162 | case 0x60: if ((IR&0x1F)!=0xB) { if((IR&3)==3) {T=(memory[addr]>>1)+(ST&1)*128; ST&=124; ST|=(T&1); memory[addr]=T; cycles+=2;} //ADC / RRA (ROR+ADC) 163 | T=A; A+=memory[addr]+(ST&1); ST&=60; ST|=(A&128)|(A>255); A&=0xFF; ST |= (!A)<<1 | ( !((T^memory[addr])&0x80) & ((T^A)&0x80) ) >> 1; } 164 | else { A&=memory[addr]; T+=memory[addr]+(ST&1); ST&=60; ST |= (T>255) | ( !((A^memory[addr])&0x80) & ((T^A)&0x80) ) >> 1; //V-flag set by intermediate ADC mechanism: (A&mem)+mem 165 | T=A; A=(A>>1)+(ST&1)*128; ST|=(A&128)|(T>127); ST|=(!A)<<1; } break; // ARR (AND+ROR, bit0 not going to C, but C and bit7 get exchanged.) 166 | case 0xE0: if((IR&3)==3 && (IR&0x1F)!=0xB) {memory[addr]++;cycles+=2;} T=A; A-=memory[addr]+!(ST&1); //SBC / ISC(ISB)=INC+SBC 167 | ST&=60; ST|=(A&128)|(A>=0); A&=0xFF; ST |= (!A)<<1 | ( ((T^memory[addr])&0x80) & ((T^A)&0x80) ) >> 1; break; 168 | case 0xC0: if((IR&0x1F)!=0xB) { if ((IR&3)==3) {memory[addr]--; cycles+=2;} T=A-memory[addr]; } // CMP / DCP(DEC+CMP) 169 | else {X=T=(A&X)-memory[addr];} /*SBX(AXS)*/ ST&=124;ST|=(!(T&0xFF))<<1|(T&128)|(T>=0); break; //SBX (AXS) (CMP+DEX at the same time) 170 | case 0x00: if ((IR&0x1F)!=0xB) { if ((IR&3)==3) {ST&=124; ST|=(memory[addr]>127); memory[addr]<<=1; cycles+=2;} 171 | A|=memory[addr]; ST&=125;ST|=(!A)<<1|(A&128); } //ORA / SLO(ASO)=ASL+ORA 172 | else {A&=memory[addr]; ST&=124;ST|=(!A)<<1|(A&128)|(A>127);} break; //ANC (AND+Carry=bit7) 173 | case 0x20: if ((IR&0x1F)!=0xB) { if ((IR&3)==3) {T=(memory[addr]<<1)+(ST&1); ST&=124; ST|=(T>255); T&=0xFF; memory[addr]=T; cycles+=2;} 174 | A&=memory[addr]; ST&=125; ST|=(!A)<<1|(A&128); } //AND / RLA (ROL+AND) 175 | else {A&=memory[addr]; ST&=124;ST|=(!A)<<1|(A&128)|(A>127);} break; //ANC (AND+Carry=bit7) 176 | case 0x40: if ((IR&0x1F)!=0xB) { if ((IR&3)==3) {ST&=124; ST|=(memory[addr]&1); memory[addr]>>=1; cycles+=2;} 177 | A^=memory[addr]; ST&=125;ST|=(!A)<<1|(A&128); } //EOR / SRE(LSE)=LSR+EOR 178 | else {A&=memory[addr]; ST&=124; ST|=(A&1); A>>=1; A&=0xFF; ST|=(A&128)|((!A)<<1); } break; //ALR(ASR)=(AND+LSR) 179 | case 0xA0: if ((IR&0x1F)!=0x1B) { A=memory[addr]; if((IR&3)==3) X=A; } //LDA / LAX (illegal, used by my 1 rasterline player) 180 | else {A=X=SP=memory[addr]&SP;} /*LAS(LAR)*/ ST&=125; ST|=((!A)<<1) | (A&128); break; // LAS (LAR) 181 | case 0x80: if ((IR&0x1F)==0xB) { A = X & memory[addr]; ST&=125; ST|=(A&128) | ((!A)<<1); } //XAA (TXA+AND), highly unstable on real 6502! 182 | else if ((IR&0x1F)==0x1B) { SP=A&X; memory[addr]=SP&((addr>>8)+1); } //TAS(SHS) (SP=A&X, mem=S&H} - unstable on real 6502 183 | else {memory[addr]=A & (((IR&3)==3)?X:0xFF); storadd=addr;} break; //STA / SAX (at times same as AHX/SHX/SHY) (illegal) 184 | } 185 | } 186 | 187 | else if(IR&2) { //nybble2: 2:illegal/LDX, 6:A/X/INC/DEC, A:Accu-shift/reg.transfer/NOP, E:shift/X/INC/DEC 188 | switch (IR&0x1F) { //addressing modes 189 | case 0x1E: PC++; addr=memory[PC]; PC++; addr+=memory[PC]*256 + ( ((IR&0xC0)!=0x80) ? X:Y ); cycles=5; break; //abs,x / abs,y 190 | case 0xE: PC++; addr=memory[PC]; PC++; addr+=memory[PC]*256; cycles=4; break; //abs 191 | case 0x16: PC++; addr = memory[PC] + ( ((IR&0xC0)!=0x80) ? X:Y ); cycles=4; break; //zp,x / zp,y 192 | case 6: PC++; addr = memory[PC]; cycles=3; break; //zp 193 | case 2: PC++; addr = PC; cycles=2; //imm. 194 | } 195 | addr&=0xFFFF; 196 | switch (IR&0xE0) { 197 | case 0x00: ST&=0xFE; case 0x20: if((IR&0xF)==0xA) { A=(A<<1)+(ST&1); ST&=124;ST|=(A&128)|(A>255); A&=0xFF; ST|=(!A)<<1; } //ASL/ROL (Accu) 198 | else { T=(memory[addr]<<1)+(ST&1); ST&=124;ST|=(T&128)|(T>255); T&=0xFF; ST|=(!T)<<1; memory[addr]=T; cycles+=2; } break; //RMW (Read-Write-Modify) 199 | case 0x40: ST&=0xFE; case 0x60: if((IR&0xF)==0xA) { T=A; A=(A>>1)+(ST&1)*128; ST&=124;ST|=(A&128)|(T&1); A&=0xFF; ST|=(!A)<<1; } //LSR/ROR (Accu) 200 | else { T=(memory[addr]>>1)+(ST&1)*128; ST&=124;ST|=(T&128)|(memory[addr]&1); T&=0xFF; ST|=(!T)<<1; memory[addr]=T; cycles+=2; } break; //memory (RMW) 201 | case 0xC0: if(IR&4) { memory[addr]--; ST&=125;ST|=(!memory[addr])<<1|(memory[addr]&128); cycles+=2; } //DEC 202 | else {X--; X&=0xFF; ST&=125;ST|=(!X)<<1|(X&128);} break; //DEX 203 | case 0xA0: if((IR&0xF)!=0xA) X=memory[addr]; else if(IR&0x10) {X=SP;break;} else X=A; ST&=125;ST|=(!X)<<1|(X&128); break; //LDX/TSX/TAX 204 | case 0x80: if(IR&4) {memory[addr]=X;storadd=addr;} else if(IR&0x10) SP=X; else {A=X; ST&=125;ST|=(!A)<<1|(A&128);} break; //STX/TXS/TXA 205 | case 0xE0: if(IR&4) { memory[addr]++; ST&=125;ST|=(!memory[addr])<<1|(memory[addr]&128); cycles+=2; } //INC/NOP 206 | } 207 | } 208 | 209 | else if((IR&0xC)==8) { //nybble2: 8:register/status 210 | switch (IR&0xF0) { 211 | case 0x60: SP++; SP&=0xFF; A=memory[0x100+SP]; ST&=125;ST|=(!A)<<1|(A&128); cycles=4; break; //PLA 212 | case 0xC0: Y++; Y&=0xFF; ST&=125;ST|=(!Y)<<1|(Y&128); break; //INY 213 | case 0xE0: X++; X&=0xFF; ST&=125;ST|=(!X)<<1|(X&128); break; //INX 214 | case 0x80: Y--; Y&=0xFF; ST&=125;ST|=(!Y)<<1|(Y&128); break; //DEY 215 | case 0x00: memory[0x100+SP]=ST; SP--; SP&=0xFF; cycles=3; break; //PHP 216 | case 0x20: SP++; SP&=0xFF; ST=memory[0x100+SP]; cycles=4; break; //PLP 217 | case 0x40: memory[0x100+SP]=A; SP--; SP&=0xFF; cycles=3; break; //PHA 218 | case 0x90: A=Y; ST&=125;ST|=(!A)<<1|(A&128); break; //TYA 219 | case 0xA0: Y=A; ST&=125;ST|=(!Y)<<1|(Y&128); break; //TAY 220 | default: if(flagsw[IR>>5]&0x20) ST|=(flagsw[IR>>5]&0xDF); else ST&=255-(flagsw[IR>>5]&0xDF); //CLC/SEC/CLI/SEI/CLV/CLD/SED 221 | } 222 | } 223 | 224 | else { //nybble2: 0: control/branch/Y/compare 4: Y/compare C:Y/compare/JMP 225 | if ((IR&0x1F)==0x10) { PC++; T=memory[PC]; if(T&0x80) T-=0x100; //BPL/BMI/BVC/BVS/BCC/BCS/BNE/BEQ relative branch 226 | if(IR&0x20) {if (ST&branchflag[IR>>6]) {PC+=T;cycles=3;}} else {if (!(ST&branchflag[IR>>6])) {PC+=T;cycles=3;}} } 227 | else { //nybble2: 0:Y/control/Y/compare 4:Y/compare C:Y/compare/JMP 228 | switch (IR&0x1F) { //addressing modes 229 | case 0: PC++; addr = PC; cycles=2; break; //imm. (or abs.low for JSR/BRK) 230 | case 0x1C: PC++; addr=memory[PC]; PC++; addr+=memory[PC]*256 + X; cycles=5; break; //abs,x 231 | case 0xC: PC++; addr=memory[PC]; PC++; addr+=memory[PC]*256; cycles=4; break; //abs 232 | case 0x14: PC++; addr = memory[PC] + X; cycles=4; break; //zp,x 233 | case 4: PC++; addr = memory[PC]; cycles=3; //zp 234 | } 235 | addr&=0xFFFF; 236 | switch (IR&0xE0) { 237 | case 0x00: memory[0x100+SP]=PC%256; SP--;SP&=0xFF; memory[0x100+SP]=PC/256; SP--;SP&=0xFF; memory[0x100+SP]=ST; SP--;SP&=0xFF; 238 | PC = memory[0xFFFE]+memory[0xFFFF]*256-1; cycles=7; break; //BRK 239 | case 0x20: if(IR&0xF) { ST &= 0x3D; ST |= (memory[addr]&0xC0) | ( !(A&memory[addr]) )<<1; } //BIT 240 | else { memory[0x100+SP]=(PC+2)%256; SP--;SP&=0xFF; memory[0x100+SP]=(PC+2)/256; SP--;SP&=0xFF; PC=memory[addr]+memory[addr+1]*256-1; cycles=6; } break; //JSR 241 | case 0x40: if(IR&0xF) { PC = addr-1; cycles=3; } //JMP 242 | else { if(SP>=0xFF) return 0xFE; SP++;SP&=0xFF; ST=memory[0x100+SP]; SP++;SP&=0xFF; T=memory[0x100+SP]; SP++;SP&=0xFF; PC=memory[0x100+SP]+T*256-1; cycles=6; } break; //RTI 243 | case 0x60: if(IR&0xF) { PC = memory[addr]+memory[addr+1]*256-1; cycles=5; } //JMP() (indirect) 244 | else { if(SP>=0xFF) return 0xFF; SP++;SP&=0xFF; T=memory[0x100+SP]; SP++;SP&=0xFF; PC=memory[0x100+SP]+T*256-1; cycles=6; } break; //RTS 245 | case 0xC0: T=Y-memory[addr]; ST&=124;ST|=(!(T&0xFF))<<1|(T&128)|(T>=0); break; //CPY 246 | case 0xE0: T=X-memory[addr]; ST&=124;ST|=(!(T&0xFF))<<1|(T&128)|(T>=0); break; //CPX 247 | case 0xA0: Y=memory[addr]; ST&=125;ST|=(!Y)<<1|(Y&128); break; //LDY 248 | case 0x80: memory[addr]=Y; storadd=addr; //STY 249 | } 250 | } 251 | } 252 | 253 | PC++; //PC&=0xFFFF; 254 | return 0; 255 | } 256 | 257 | 258 | 259 | // //----------------------------- SID emulation ----------------------------------------- 260 | 261 | // Arrays to support the emulation: 262 | #include "precalc.inc" 263 | 264 | #define PERIOD0 CLOCK_RATIO_DEFAULT //max(round(clock_ratio),9) 265 | #define STEP0 3 //ceil(PERIOD0/9.0) 266 | 267 | float ADSRperiods[16] = {PERIOD0, 32, 63, 95, 149, 220, 267, 313, 392, 977, 1954, 3126, 3907, 11720, 19532, 31251}; 268 | byte ADSRstep[16] = { STEP0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; 269 | 270 | const byte ADSR_exptable[256] = {1, 30, 30, 30, 30, 30, 30, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, //pos0:1 pos6:30 pos14:16 pos26:8 271 | 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, //pos54:4 //pos93:2 272 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 273 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 274 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 275 | 276 | 277 | void cSID_init(int samplerate) 278 | { 279 | int i; 280 | clock_ratio = C64_PAL_CPUCLK/samplerate; 281 | if (clock_ratio>9) { ADSRperiods[0]=clock_ratio; ADSRstep[0]=ceil(clock_ratio/9.0); } 282 | else { ADSRperiods[0]=9.0; ADSRstep[0]=1; } 283 | cutoff_ratio_8580 = -2 * 3.14 * (12500 / 2048) / samplerate; // -2 * 3.14 * ((82000/6.8) / 2048) / samplerate; //approx. 30Hz..12kHz according to datasheet, but only for 6.8nF value, 22nF makes 9Hz...3.7kHz? wrong 284 | cap_6581_reciprocal = -1000000/CAP_6581; //lighten CPU-load in sample-callback 285 | cutoff_steepness_6581 = FILTER_DARKNESS_6581*(2048.0-VCR_FET_TRESHOLD); //pre-scale for 0...2048 cutoff-value range //lighten CPU-load in sample-callback 286 | // cutoff_bottom_6581 = 1 - exp( -1 / (0.000000000470*1500000) / samplerate ); // 1 - exp( -2 * 3.14 * (26000/pow(2,9)/0.47) / samplerate ); //around 140..220Hz cutoff is set by VCR-MOSFET limiter/shunt-resistor (1.5MOhm) 287 | // cutoff_top_6581 = 20000; //Hz // (26000/0.47); // 1 - exp( -2 * 3.14 * (26000/0.47) / samplerate); //cutoff range is 9 octaves stated by datasheet, but process variation might eliminate any filter spec. 288 | // cutoff_ratio_6581 = -2 * 3.14 * (cutoff_top_6581 / 2048) / samplerate; //(cutoff_top_6581-cutoff_bottom_6581)/(2048.0-192.0); //datasheet: 30Hz..12kHz with 2.2pF -> 140Hz..56kHz with 470pF? 289 | 290 | // createCombinedWF(TriSaw_8580, 0.8, 2.4, 0.64); 291 | // createCombinedWF(PulseSaw_8580, 1.4, 1.9, 0.68); 292 | // createCombinedWF(PulseTriSaw_8580, 0.8, 2.5, 0.64); 293 | 294 | for(i = 0; i < 9; i++) { 295 | ADSRstate[i] = HOLDZERO_BITMASK; 296 | envcnt[i] = 0; 297 | ratecnt[i] = 0; 298 | phaseaccu[i] = 0; 299 | prevaccu[i] = 0; 300 | expcnt[i] = 0; 301 | prevSR[i]=0; 302 | noise_LFSR[i] = 0x7FFFFF; 303 | prevwfout[i] = 0; 304 | } 305 | 306 | for(i = 0; i < 3; i++) { 307 | sourceMSBrise[i] = 0; 308 | sourceMSB[i] = 0; 309 | prevlowpass[i] = 0; 310 | prevbandpass[i] = 0; 311 | } 312 | 313 | initSID(); 314 | } 315 | 316 | //registers: 0:freql1 1:freqh1 2:pwml1 3:pwmh1 4:ctrl1 5:ad1 6:sr1 7:freql2 8:freqh2 9:pwml2 10:pwmh2 11:ctrl2 12:ad2 13:sr 14:freql3 15:freqh3 16:pwml3 17:pwmh3 18:ctrl3 19:ad3 20:sr3 317 | // 21:cutoffl 22:cutoffh 23:flsw_reso 24:vol_ftype 25:potX 26:potY 27:OSC3 28:ENV3 318 | void initSID() { 319 | int i; 320 | for(i=0xD400; i<=0xD7FF; i++) memory[i] = 0; 321 | for(i=0xDE00; i<=0xDFFF; i++) memory[i] = 0; 322 | for(i=0; i<9; i++) { 323 | ADSRstate[i] = HOLDZERO_BITMASK; 324 | ratecnt[i] = envcnt[i] = expcnt[i] = 0; 325 | } 326 | } 327 | 328 | 329 | //My SID implementation is similar to what I worked out in a SwinSID variant during 3..4 months of development. (So jsSID only took 2 weeks armed with this experience.) 330 | //I learned the workings of ADSR/WAVE/filter operations mainly from the quite well documented resid and resid-fp codes. 331 | //(The SID reverse-engineering sites were also good sources.) 332 | //Note that I avoided many internal/automatic variables from the SID function, assuming better speed this way. (Not using stack as much, but I'm not sure and it may depend on platform...) 333 | //(The same is true for CPU emulation and player-code.) 334 | int SID(unsigned char num, unsigned int baseaddr) //the SID emulation itself ('num' is the number of SID to iterate (0..2) 335 | { 336 | //better keep these variables static so they won't slow down the routine like if they were internal automatic variables always recreated 337 | static byte channel, ctrl, SR, prevgate, wf, test, *sReg, *vReg; 338 | static unsigned int accuadd, MSB, pw, wfout; 339 | static int tmp, step, lim, nonfilt, filtin, filtout, output; 340 | static float period, steep, rDS_VCR_FET, cutoff[3], resonance[3], ftmp; 341 | 342 | filtin=nonfilt=0; sReg = &memory[baseaddr]; vReg = sReg; 343 | 344 | //treating 2SID and 3SID channels uniformly (0..5 / 0..8), this probably avoids some extra code 345 | for (channel = num * SID_CHANNEL_AMOUNT ; channel < (num + 1) * SID_CHANNEL_AMOUNT ; channel++, vReg += 7) { 346 | ctrl = vReg[4]; 347 | 348 | //ADSR envelope-generator: 349 | SR = vReg[6]; tmp = 0; 350 | prevgate = (ADSRstate[channel] & GATE_BITMASK); 351 | if (prevgate != (ctrl & GATE_BITMASK)) { //gatebit-change? 352 | if (prevgate) ADSRstate[channel] &= 0xFF - (GATE_BITMASK | ATTACK_BITMASK | DECAYSUSTAIN_BITMASK); 353 | else { //falling edge 354 | ADSRstate[channel] = (GATE_BITMASK | ATTACK_BITMASK | DECAYSUSTAIN_BITMASK); //rising edge, also sets hold_zero_bit=0 355 | if ((SR & 0xF) > (prevSR[channel] & 0xF)) tmp = 1; //assume SR->GATE write order: workaround to have crisp soundstarts by triggering delay-bug 356 | } //(this is for the possible missed CTRL(GATE) vs SR register write order situations (1MHz CPU is cca 20 times faster than samplerate) 357 | } 358 | prevSR[channel] = SR; //if(SR&0xF) ratecnt[channel]+=5; //assume SR->GATE write order: workaround to have crisp soundstarts by triggering delay-bug 359 | ratecnt[channel] += clock_ratio; if (ratecnt[channel] >= 0x8000) ratecnt[channel] -= 0x8000; //can wrap around (ADSR delay-bug: short 1st frame) 360 | //set ADSR period that should be checked against rate-counter (depending on ADSR state Attack/DecaySustain/Release) 361 | if (ADSRstate[channel] & ATTACK_BITMASK) step = vReg[5] >> 4; 362 | else if (ADSRstate[channel] & DECAYSUSTAIN_BITMASK) step = vReg[5] & 0xF; 363 | else step = SR & 0xF; 364 | period = ADSRperiods[step]; step = ADSRstep[step]; 365 | if (ratecnt[channel] >= period && ratecnt[channel] < period + clock_ratio && tmp == 0) { //ratecounter shot (matches rateperiod) (in genuine SID ratecounter is LFSR) 366 | ratecnt[channel] -= period; //compensation for timing instead of simply setting 0 on rate-counter overload 367 | if ((ADSRstate[channel] & ATTACK_BITMASK) || ++expcnt[channel] == ADSR_exptable[envcnt[channel]]) { 368 | if (!(ADSRstate[channel] & HOLDZERO_BITMASK)) { 369 | if (ADSRstate[channel] & ATTACK_BITMASK) 370 | { envcnt[channel]+=step; if (envcnt[channel]>=0xFF) {envcnt[channel]=0xFF; ADSRstate[channel] &= 0xFF-ATTACK_BITMASK;} } 371 | else if ( !(ADSRstate[channel] & DECAYSUSTAIN_BITMASK) || envcnt[channel] > (SR&0xF0) + (SR>>4) ) 372 | { envcnt[channel]-=step; if (envcnt[channel]<=0 && envcnt[channel]+step!=0) {envcnt[channel]=0; ADSRstate[channel]|=HOLDZERO_BITMASK;} } 373 | } 374 | expcnt[channel] = 0; 375 | } 376 | } 377 | envcnt[channel] &= 0xFF; 378 | 379 | //WAVE-generation code (phase accumulator and waveform-selector): 380 | test = ctrl & TEST_BITMASK; wf = ctrl & 0xF0; accuadd = (vReg[0] + vReg[1] * 256) * clock_ratio; 381 | if (test || ((ctrl & SYNC_BITMASK) && sourceMSBrise[num])) phaseaccu[channel] = 0; 382 | else { phaseaccu[channel] += accuadd; if (phaseaccu[channel] > 0xFFFFFF) phaseaccu[channel] -= 0x1000000; } 383 | phaseaccu[channel] &= 0xFFFFFF; MSB = phaseaccu[channel] & 0x800000; sourceMSBrise[num] = (MSB > (prevaccu[channel] & 0x800000)) ? 1 : 0; 384 | if (wf & NOISE_BITMASK) { //noise waveform 385 | tmp = noise_LFSR[channel]; 386 | if (((phaseaccu[channel] & 0x100000) != (prevaccu[channel] & 0x100000)) || accuadd >= 0x100000) //clock LFSR all time if clockrate exceeds observable at given samplerate 387 | { step = (tmp & 0x400000) ^ ((tmp & 0x20000) << 5); tmp = ((tmp << 1) + (step ? 1 : test)) & 0x7FFFFF; noise_LFSR[channel]=tmp; } 388 | //we simply zero output when other waveform is mixed with noise. On real SID LFSR continuously gets filled by zero and locks up. ($C1 waveform with pw<8 can keep it for a while...) 389 | wfout = (wf & 0x70) ? 0 : ((tmp & 0x100000) >> 5) + ((tmp & 0x40000) >> 4) + ((tmp & 0x4000) >> 1) + ((tmp & 0x800) << 1) + ((tmp & 0x200) << 2) + ((tmp & 0x20) << 5) + ((tmp & 0x04) << 7) + ((tmp & 0x01) << 8); 390 | } 391 | else if (wf & PULSE_BITMASK) { //simple pulse 392 | pw = (vReg[2] + (vReg[3] & 0xF) * 256) * 16; tmp = (int) accuadd >> 9; 393 | if (0 < pw && pw < tmp) pw = tmp; tmp ^= 0xFFFF; if (pw > tmp) pw = tmp; 394 | tmp = phaseaccu[channel] >> 8; 395 | if (wf == PULSE_BITMASK) { //simple pulse, most often used waveform, make it sound as clean as possible without oversampling 396 | //One of my biggest success with the SwinSID-variant was that I could clean the high-pitched and thin sounds. 397 | //(You might have faced with the unpleasant sound quality of high-pitched sounds without oversampling. We need so-called 'band-limited' synthesis instead. 398 | // There are a lot of articles about this issue on the internet. In a nutshell, the harsh edges produce harmonics that exceed the 399 | // Nyquist frequency (samplerate/2) and they are folded back into hearable range, producing unvanted ringmodulation-like effect.) 400 | //After so many trials with dithering/filtering/oversampling/etc. it turned out I can't eliminate the fukkin aliasing in time-domain, as suggested at pages. 401 | //Oversampling (running the wave-generation 8 times more) was not a way at 32MHz SwinSID. It might be an option on PC but I don't prefer it in JavaScript.) 402 | //The only solution that worked for me in the end, what I came up with eventually: The harsh rising and falling edges of the pulse are 403 | //elongated making it a bit trapezoid. But not in time-domain, but altering the transfer-characteristics. This had to be done 404 | //in a frequency-dependent way, proportionally to pitch, to keep the deep sounds crisp. The following code does this (my favourite testcase is Robocop3 intro): 405 | step = (accuadd>=255)? 65535/(accuadd/256.0) : 0xFFFF; //simple pulse, most often used waveform, make it sound as clean as possible without oversampling 406 | if (test) wfout=0xFFFF; 407 | else if (tmp0xFFFF) lim=0xFFFF; tmp=lim-(pw-tmp)*step; wfout=(tmp<0)?0:tmp; } //rising edge 408 | else { lim=pw*step; if (lim>0xFFFF) lim=0xFFFF; tmp=(0xFFFF-tmp)*step-lim; wfout=(tmp>=0)?0xFFFF:tmp; } //falling edge 409 | } 410 | else { //combined pulse 411 | wfout = (tmp >= pw || test) ? 0xFFFF:0; //(this would be enough for a simple but aliased-at-high-pitches pulse) 412 | if (wf&TRI_BITMASK) { 413 | if (wf&SAW_BITMASK) { wfout = wfout? combinedWF(num,channel,PulseTriSaw_8580,tmp>>4,1,vReg[1]) : 0; } //pulse+saw+triangle (waveform nearly identical to tri+saw) 414 | else { tmp=phaseaccu[channel]^(ctrl&RING_BITMASK?sourceMSB[num]:0); wfout = (wfout)? combinedWF(num,channel,PulseSaw_8580,(tmp^(tmp&0x800000?0xFFFFFF:0))>>11,0,vReg[1]) : 0; } } //pulse+triangle 415 | else if (wf&SAW_BITMASK) wfout = wfout? combinedWF(num,channel,PulseSaw_8580,tmp>>4,1,vReg[1]) : 0; //pulse+saw 416 | } 417 | } 418 | else if (wf&SAW_BITMASK) { //saw 419 | wfout=phaseaccu[channel]>>8; //saw (this row would be enough for simple but aliased-at-high-pitch saw) 420 | //The anti-aliasing (cleaning) of high-pitched sawtooth wave works by the same principle as mentioned above for the pulse, 421 | //but the sawtooth has even harsher edge/transition, and as the falling edge gets longer, tha rising edge should became shorter, 422 | //and to keep the amplitude, it should be multiplied a little bit (with reciprocal of rising-edge steepness). 423 | //The waveform at the output essentially becomes an asymmetric triangle, more-and-more approaching symmetric shape towards high frequencies. 424 | //(If you check a recording from the real SID, you can see a similar shape, the high-pitch sawtooth waves are triangle-like...) 425 | //But for deep sounds the sawtooth is really close to a sawtooth, as there is no aliasing there, but deep sounds should be sharp... 426 | if (wf&TRI_BITMASK) wfout = combinedWF(num,channel,TriSaw_8580,wfout>>4,1,vReg[1]); //saw+triangle 427 | else { //simple cleaned (bandlimited) saw 428 | steep=(accuadd/65536.0)/288.0; 429 | wfout += wfout*steep; if(wfout>0xFFFF) wfout=0xFFFF-(wfout-0x10000)/steep; 430 | } 431 | } 432 | else if (wf&TRI_BITMASK) { //triangle (this waveform has no harsh edges, so it doesn't suffer from strong aliasing at high pitches) 433 | tmp=phaseaccu[channel]^(ctrl&RING_BITMASK?sourceMSB[num]:0); wfout = (tmp^(tmp&0x800000?0xFFFFFF:0)) >> 7; 434 | } 435 | wfout&=0xFFFF; if (wf) prevwfout[channel] = wfout; else { wfout = prevwfout[channel]; } //emulate waveform 00 floating wave-DAC (on real SID waveform00 decays after 15s..50s depending on temperature?) 436 | prevaccu[channel] = phaseaccu[channel]; sourceMSB[num] = MSB; //(So the decay is not an exact value. Anyway, we just simply keep the value to avoid clicks and support SounDemon digi later...) 437 | 438 | //routing the channel signal to either the filter or the unfiltered master output depending on filter-switch SID-registers 439 | if (sReg[0x17] & FILTSW[channel]) filtin += ((int)wfout - 0x8000) * envcnt[channel] / 256; 440 | else if ((FILTSW[channel] != 4) || !(sReg[0x18] & OFF3_BITMASK)) 441 | nonfilt += ((int)wfout - 0x8000) * envcnt[channel] / 256; 442 | } 443 | //update readable SID1-registers (some SID tunes might use 3rd channel ENV3/OSC3 value as control) 444 | if(num==0, memory[1]&3) { sReg[0x1B]=wfout>>8; sReg[0x1C]=envcnt[3]; } //OSC3, ENV3 (some players rely on it) 445 | 446 | //FILTER: two integrator loop bi-quadratic filter, workings learned from resid code, but I kindof simplified the equations 447 | //The phases of lowpass and highpass outputs are inverted compared to the input, but bandpass IS in phase with the input signal. 448 | //The 8580 cutoff frequency control-curve is ideal (binary-weighted resistor-ladder VCRs), while the 6581 has a treshold, and below that it 449 | //outputs a constant ~200Hz cutoff frequency. (6581 uses MOSFETs as VCRs to control cutoff causing nonlinearity and some 'distortion' due to resistance-modulation. 450 | //There's a cca. 1.53Mohm resistor in parallel with the MOSFET in 6581 which doesn't let the frequency go below 200..220Hz 451 | //Even if the MOSFET doesn't conduct at all. 470pF capacitors are small, so 6581 can't go below this cutoff-frequency with 1.5MOhm.) 452 | cutoff[num] = sReg[0x16] * 8 + (sReg[0x15] & 7); 453 | if (SID_model[num] == 8580) { 454 | cutoff[num] = ( 1 - exp((cutoff[num]+2) * cutoff_ratio_8580) ); //linear curve by resistor-ladder VCR 455 | resonance[num] = ( pow(2, ((4 - (sReg[0x17] >> 4)) / 8.0)) ); 456 | } 457 | else { //6581 458 | cutoff[num] += round(filtin*FILTER_DISTORTION_6581); //MOSFET-VCR control-voltage-modulation (resistance-modulation aka 6581 filter distortion) emulation 459 | rDS_VCR_FET = cutoff[num]<=VCR_FET_TRESHOLD ? 100000000.0 //below Vth treshold Vgs control-voltage FET presents an open circuit 460 | : cutoff_steepness_6581/(cutoff[num]-VCR_FET_TRESHOLD); // rDS ~ (-Vth*rDSon) / (Vgs-Vth) //above Vth FET drain-source resistance is proportional to reciprocal of cutoff-control voltage 461 | cutoff[num] = ( 1 - exp( cap_6581_reciprocal / (VCR_SHUNT_6581*rDS_VCR_FET/(VCR_SHUNT_6581+rDS_VCR_FET)) / samplerate ) ); //curve with 1.5MOhm VCR parallel Rshunt emulation 462 | resonance[num] = ( (sReg[0x17] > 0x5F) ? 8.0 / (sReg[0x17] >> 4) : 1.41 ); 463 | } 464 | filtout=0; 465 | ftmp = filtin + prevbandpass[num] * resonance[num] + prevlowpass[num]; 466 | if (sReg[0x18] & HIGHPASS_BITMASK) filtout -= ftmp; 467 | ftmp = prevbandpass[num] - ftmp * cutoff[num]; 468 | prevbandpass[num] = ftmp; 469 | if (sReg[0x18] & BANDPASS_BITMASK) filtout -= ftmp; 470 | ftmp = prevlowpass[num] + ftmp * cutoff[num]; 471 | prevlowpass[num] = ftmp; 472 | if (sReg[0x18] & LOWPASS_BITMASK) filtout += ftmp; 473 | 474 | //output stage for one SID 475 | //when it comes to $D418 volume-register digi playback, I made an AC / DC separation for $D418 value in the SwinSID at low (20Hz or so) cutoff-frequency, 476 | //and sent the AC (highpass) value to a 4th 'digi' channel mixed to the master output, and set ONLY the DC (lowpass) value to the volume-control. 477 | //This solved 2 issues: Thanks to the lowpass filtering of the volume-control, SID tunes where digi is played together with normal SID channels, 478 | //won't sound distorted anymore, and the volume-clicks disappear when setting SID-volume. (This is useful for fade-in/out tunes like Hades Nebula, where clicking ruins the intro.) 479 | output = (nonfilt+filtout) * (sReg[0x18]&0xF) / OUTPUT_SCALEDOWN; 480 | if (output>=32767) output=32767; else if (output<=-32768) output=-32768; //saturation logic on overload (not needed if the callback handles it) 481 | return (int)output; // master output 482 | } 483 | 484 | 485 | //The anatomy of combined waveforms: The resid source simply uses 4kbyte 8bit samples from wavetable arrays, says these waveforms are mystic due to the analog behaviour. 486 | //It's true, the analog things inside SID play a significant role in how the combined waveforms look like, but process variations are not so huge that cause much differences in SIDs. 487 | //After checking these waveforms by eyes, it turned out for me that these waveform are fractal-like, recursively approachable waveforms. 488 | //My 1st thought and trial was to store only a portion of the waveforms in table, and magnify them depending on phase-accumulator's state. 489 | //But I wanted to understand how these waveforms are produced. I felt from the waveform-diagrams that the bits of the waveforms affect each other, 490 | //hence the recursive look. A short C code proved by assumption, I could generate something like a pulse+saw combined waveform. 491 | //Recursive calculations were not feasible for MCU of SwinSID, but for jsSID I could utilize what I found out and code below generates the combined waveforms into wavetables. 492 | //To approach the combined waveforms as much as possible, I checked out the SID schematic that can be found at some reverse-engineering sites... 493 | //The SID's R-2R ladder WAVE DAC is driven by operation-amplifier like complementary FET output drivers, so that's not the place where I first thought the magic happens. 494 | //These 'opamps' (for all 12 wave-bits) have single FETs as inputs, and they switch on above a certain level of input-voltage, causing 0 or 1 bit as R-2R DAC input. 495 | //So the first keyword for the workings is TRESHOLD. These FET inputs are driven through serial switch FETs (wave-selector) that normally enables one waveform at a time. 496 | //The phase-accumulator's output is brought to 3 kinds of circuitries for the 3 basic waveforms. The pulse simply drives 497 | //all wave-selector inputs with a 0/1 depending on pulsewidth, the sawtooth has a XOR for triangle/ringmod generation, but what 498 | //is common for all waveforms, they have an open-drain driver before the wave-selector, which has FETs towards GND and 'FET resistor' towards the power-supply rail. 499 | //These outputs are clearly not designed to drive high loads, and normally they only have to drive the FETs input mentioned above. 500 | //But when more of these output drivers are switched together by the switch-FETs in the wave-selector, they affect each other by loading each other. 501 | //The pulse waveform, when selected, connects all of them together through a fairly strong connection, and its signal also affects the analog level (pulls below the treshold)... 502 | //The farther a specific DAC bit driver is from the other, the less it affects its output. It turned out it's not powers of 2 but something else, 503 | //that creates similar combined waveforms to that of real SID's... Note that combined waveforms never have values bigger than their sourcing sawtooth wave. 504 | //The analog levels that get generated by the various bit drivers, that pull each other up/DOWN, depend on the resistances the components/wires inside the SID. 505 | //And finally, what is output on the DAC depends on whether these analog levels are below or above the FET gate's treshold-level, 506 | //That's how the combined waveform is generated. Maybe I couldn't explain well enough, but the code below is simple enough to understand the mechanism algoritmically. 507 | //This simplified schematic exapmle might make it easier to understand sawtooth+pulse combination (must be observed with monospace fonts): 508 | // _____ |- .--------------. /\/\--. 509 | // Vsupply / .----| |---------*---|- / Vsupply ! R ! As can be seen on this schematic, 510 | // ------. other ! ! _____ ! TRES \ \ ! / the pulse wave-selector FETs 511 | // ! saw bit *--!----| |---------' HOLD / ! |- 2R \ connect the neighbouring sawtooth 512 | // / output ! ! ! |------|- / outputs with a fairly strong 513 | // Rd \ |- !WAVEFORM-SELECTOR *--*---|- ! R ! connection to each other through 514 | // / |- !SWITCHING FETs ! ! ! *---/\/\--* their own wave-selector FETs. 515 | // ! saw-bit ! _____ |- ! --- ! ! So the adjacent sawtooth outputs 516 | // *------------------!-----| |-----------*-----|- ! |- / pull each other lower (or maybe a bit upper but not exceeding sawtooth line) 517 | // ! (weak drive,so ! saw switch ! TRES-! `----------|- 2R \ depending on their low/high state and 518 | // |- can be shifted ! ! HOLD ! ! / distance from each other, causing 519 | // -----|- down (& up?) ! _____ ! ! ! R ! the resulting analog level that 520 | // ! by neighbours) *-----| |-----------' --- --- /\/\-* will either turn the output on or not. 521 | // GND --- ! pulse switch ! (Depending on their relation to treshold.) 522 | // 523 | //(As triangle waveform connects adjacent bits by default, the above explained effect becomes even stronger, that's why combined waveforms with thriangle are at 0 level most of the time.) 524 | 525 | //in case you don't like these calculated combined waveforms it's easy to substitute the generated tables by pre-sampled 'exact' versions 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | unsigned int combinedWF(unsigned char num, unsigned char channel, unsigned int* wfarray, int index, unsigned char differ6581, byte freqh) { 539 | static float addf; 540 | addf = 0.6 + 0.4 / freqh; 541 | if(differ6581 && SID_model[num] == 6581) index &= 0x7FF; 542 | prevwavdata[channel] = wfarray[index] * addf + prevwavdata[channel] * (1.0 - addf); 543 | return prevwavdata[channel]; 544 | } 545 | 546 | // void createCombinedWF(unsigned int* wfarray, float bitmul, float bitstrength, float treshold) { 547 | // int i, j, k; 548 | // for (i = 0; i < 4096; i++) { 549 | // wfarray[i] = 0; 550 | // for (j = 0; j < 12; j++) { 551 | // float bitlevel = 0; 552 | // for (k = 0; k < 12; k++) { 553 | // bitlevel += (bitmul / pow(bitstrength, fabs(k - j))) * (((i>>k)&1)-0.5); 554 | // } 555 | // wfarray[i] += (bitlevel >= treshold) ? pow(2, j) : 0; 556 | // } 557 | // wfarray[i] *= 12; 558 | // } 559 | // } 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | // 575 | // libcsid exported api 576 | // 577 | 578 | const char *libcsid_getauthor() { 579 | return (char *)&SIDauthor; 580 | } 581 | 582 | const char *libcsid_getinfo() { 583 | return (char *)&SIDinfo; 584 | } 585 | 586 | const char *libcsid_gettitle() { 587 | return (char *)&SIDtitle; 588 | } 589 | 590 | void libcsid_init(int _samplerate, int _sidmodel) { 591 | memory = (byte *)malloc(MAX_DATA_LEN); 592 | 593 | samplerate = _samplerate; 594 | sampleratio = round(C64_PAL_CPUCLK / samplerate); 595 | requested_SID_model = _sidmodel; 596 | } 597 | 598 | int libcsid_load(unsigned char *_buffer, int _bufferlen, int _subtune) { 599 | int readata, strend, subtune_amount, preferred_SID_model[3] = {8580.0, 8580.0, 8580.0}; 600 | unsigned int i, datalen, offs, loadaddr; 601 | 602 | subtune = _subtune; 603 | 604 | unsigned char *filedata = _buffer; 605 | datalen = _bufferlen; 606 | 607 | offs = filedata[7]; 608 | loadaddr = filedata[8] + filedata[9] ? filedata[8] * 256 + filedata[9] : filedata[offs] + filedata[offs + 1] * 256; 609 | printf("\nOffset: $%4.4X, Loadaddress: $%4.4X \nTimermodes:", offs, loadaddr); 610 | 611 | for (i = 0; i < 32; i++) { 612 | timermode[31 - i] = (filedata[0x12 + (i >> 3)] & (byte)pow(2, 7 - i % 8)) ? 1 : 0; 613 | printf(" %1d",timermode[31 - i]); 614 | } 615 | 616 | for (i = 0; i < MAX_DATA_LEN; i++) { 617 | memory[i] = 0; 618 | } 619 | 620 | for (i = offs + 2; i < datalen; i++) { 621 | if (loadaddr + i - (offs + 2) < MAX_DATA_LEN) { 622 | memory[loadaddr + i - (offs + 2)] = filedata[i]; 623 | } 624 | } 625 | 626 | strend = 1; 627 | for (i = 0; i < 32; i++) { 628 | if (strend != 0) { 629 | strend = SIDtitle[i] = filedata[0x16 + i]; 630 | } else { 631 | strend = SIDtitle[i] = 0; 632 | } 633 | } 634 | 635 | strend = 1; 636 | for (i = 0; i < 32; i++) { 637 | if (strend != 0) { 638 | strend = SIDauthor[i] = filedata[0x36 + i]; 639 | } else { 640 | strend = SIDauthor[i] = 0; 641 | } 642 | } 643 | 644 | strend = 1; 645 | for (i = 0; i < 32; i++) { 646 | if (strend != 0) { 647 | strend = SIDinfo[i] = filedata[0x56 + i]; 648 | } else { 649 | strend = SIDinfo[i] = 0; 650 | } 651 | } 652 | 653 | initaddr=filedata[0xA]+filedata[0xB]? filedata[0xA]*256+filedata[0xB] : loadaddr; playaddr=playaddf=filedata[0xC]*256+filedata[0xD]; printf("\nInit:$%4.4X,Play:$%4.4X, ",initaddr,playaddr); 654 | subtune_amount=filedata[0xF]; 655 | preferred_SID_model[0] = (filedata[0x77]&0x30)>=0x20? 8580 : 6581; 656 | 657 | printf("Subtunes:%d , preferred SID-model:%d", subtune_amount, preferred_SID_model[0]); 658 | 659 | preferred_SID_model[1] = (filedata[0x77]&0xC0)>=0x80 ? 8580 : 6581; 660 | preferred_SID_model[2] = (filedata[0x76]&3)>=3 ? 8580 : 6581; 661 | SID_address[1] = filedata[0x7A]>=0x42 && (filedata[0x7A]<0x80 || filedata[0x7A]>=0xE0) ? 0xD000+filedata[0x7A]*16 : 0; 662 | SID_address[2] = filedata[0x7B]>=0x42 && (filedata[0x7B]<0x80 || filedata[0x7B]>=0xE0) ? 0xD000+filedata[0x7B]*16 : 0; 663 | 664 | SIDamount=1+(SID_address[1]>0)+(SID_address[2]>0); if(SIDamount>=2) printf("(SID1), %d(SID2:%4.4X)",preferred_SID_model[1],SID_address[1]); 665 | if(SIDamount==3) printf(", %d(SID3:%4.4X)",preferred_SID_model[2],SID_address[2]); 666 | if (requested_SID_model!=-1) printf(" (requested:%d)",requested_SID_model); printf("\n"); 667 | 668 | for (i=0;i= 3) { 677 | OUTPUT_SCALEDOWN /= 0.4; 678 | } 679 | 680 | cSID_init(samplerate); 681 | init(subtune); 682 | 683 | return 0; 684 | } 685 | 686 | void libcsid_render(unsigned short *_output, int _numsamples) { 687 | play(0, (Uint8 *)_output, _numsamples * 2); 688 | } 689 | -------------------------------------------------------------------------------- /main/precalc.inc: -------------------------------------------------------------------------------- 1 | unsigned int TriSaw_8580[4096] = { 2 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0, 3 | 0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,192,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0, 4 | 0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0, 5 | 0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,384,408,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84, 6 | 0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,192,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,1536,2304,2304,2304,2304,2304,2304,2328,2304,2304,2304,2304,2304,2304,2352,2388,2688,2688,2688,2688, 7 | 2688,2688,2688,2712,2880,2880,2880,2880,2976,2976,3024,3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24, 8 | 0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192, 9 | 288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,768,768,768,852,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180, 10 | 0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,384,384,384,408,576,576,576,576,672,672,720,756,0,0,0,0, 11 | 0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,192,192,288,288,336,372,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4692,4608,4608,4608,4608,4608,4608,4608,4632,4608,4608,4608,4608,4608,4704,4752,4788,5376,5376,5376,5376,5376,5376,5376,5400, 12 | 5376,5376,5376,5376,5376,5376,5424,5460,5760,5760,5760,5760,5760,5760,5760,5784,5952,5952,5952,5952,6048,6048,6096,6132,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0, 13 | 0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84, 14 | 0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0, 15 | 0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,384,408, 16 | 576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,192,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,1536,1536,1536,1536, 17 | 1536,1632,1680,1716,2304,2304,2304,2304,2304,2304,2304,2328,2304,2304,2304,2304,2304,2304,2352,2388,2688,2688,2688,2688,2688,2688,2688,2712,2880,2880,2880,2880,2976,2976,3024,3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372, 18 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0, 19 | 0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,768,768,768,768,768,768,768,852,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0, 20 | 0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0, 21 | 0,0,0,84,0,0,0,0,384,384,384,408,6720,6720,6720,6720,6816,6816,6864,6900,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9300,9216,9216,9216,9216,9216,9216,9216,9240,9216,9216,9216,9216,9216,9216,9360,9396,9216,9216,9216,9216,9216,9216,9216,9240,9216,9216,9216,9216,9216,9216,9216,9300,9216,9216,9216,9216,9216,9216,9216,9240,9216,9216,9408,9408,9504,9504,9552,9588,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10836, 22 | 10752,10752,10752,10752,10752,10752,10752,10776,10752,10752,10752,10752,10752,10848,10896,10932,11520,11520,11520,11520,11520,11520,11520,11544,11520,11520,11520,11520,11520,11520,11568,11604,11904,11904,11904,11904,11904,11904,11904,11928,12096,12096,12096,12096,12192,12192,12240,12276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0, 23 | 0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24, 24 | 0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344, 25 | 1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180, 26 | 0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,384,408,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,192,192,288,288,336,372,0,0,0,0, 27 | 0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,2304,2304,2304,2304,2304,2304,2304,2328,2304,2304,2304,2304,2304,2304,2352,2388,2688,2688,2688,2688,2688,2688,2688,2712,2880,2880,2880,2880,2976,2976,3024,3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0, 28 | 0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0, 29 | 0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,768,768,768,768,852, 30 | 1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0, 31 | 0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,384,384,384,408,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,3072,3072,3072,3072,3072,3072,3072,3156,3072,3072,3072,3072,3072,3072,3072,3096, 32 | 3072,3072,3264,3264,3360,3360,3408,3444,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4692,4608,4608,4608,4608,4608,4608,4608,4632,4608,4608,4608,4608,4608,4704,4752,4788,5376,5376,5376,5376,5376,5376,5376,5400,5376,5376,5376,5376,5376,5376,5424,5460,5760,5760,5760,5760,5760,5760,5760,5784,5952,5952,5952,5952,6048,6048,6096,6132,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0, 33 | 0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756, 34 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0, 35 | 0,0,0,24,0,0,0,0,0,0,0,84,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0, 36 | 0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,384,384,408,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0, 37 | 0,0,0,84,0,0,0,0,0,0,0,24,0,0,192,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,1536,1536,1536,1536,1536,1536,1536,1560,1536,1536,1536,1536,1536,1632,1680,1716,2304,2304,2304,2304,2304,2304,2304,2328,2304,2304,2304,2304,2304,2304,2352,2388,2688,2688,2688,2688,2688,2688,2688,2712,2880,2880,2880,2880,2976,2976,3024,3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84, 38 | 0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,12288,12288,12288,12288,12288,12288,12288,12372,12288,12288,12288,12288,12288,12288,12288,12312,12288,12288,12288,12288,12288,12288,12432,12468,12288,12288,12288,12288,12288,12288,12288,12312,12288,12288,12288,12288,12288,12288,12288,12372,12288,12288,12288,12288, 39 | 12288,12288,12288,12312,12864,12864,12864,12864,12960,12960,13008,13044,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12372,12288,12288,12288,12288,12288,12288,12288,12312,12288,12288,12288,12288,12288,12288,12432,12468,12288,12288,12288,12288,12288,12288,12288,12312,12288,12288,12288,12288,12288,12288,12288,12372,12288,12288,12288,12288,12288,12288,12288,12312,12288,12288,12288,12480,12576,12576,12624,12660,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12372,12288,12288,12288,12288,12288,12288,12288,12312, 40 | 12288,12288,12288,12288,12288,12384,12432,12468,12288,12288,12288,12288,12288,12288,12288,12312,13056,13056,13056,13056,13056,13056,13056,13140,13440,13440,13440,13440,13440,13440,13440,13464,13632,13632,13632,13632,13728,13728,13776,13812,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43092,43008,43008,43008,43008,43008,43008,43008,43032,43008,43008,43008,43008,43008,43008,43152,43188,43008,43008,43008,43008,43008,43008,43008,43032,43008,43008,43008,43008,43008,43008,43008,43092,43008,43008,43008,43008,43008,43008,43008,43032,43008,43008,43008,43008, 41 | 43296,43296,43344,43380,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43092,43008,43008,43008,43008,43008,43008,43008,43032,43008,43008,43008,43008,43008,43104,43152,43188,43008,43008,43008,43008,43008,43008,43008,43032,43008,43008,43008,43008,43008,43008,43008,43092,43008,43008,43008,43008,43392,43392,43392,43416,43584,43584,43584,43584,43680,43680,43728,43764,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46164,46080,46080,46080,46080,46080,46080,46080,46104,46080,46080,46080,46080,46080,46080,46224,46260, 42 | 46080,46080,46080,46080,46080,46080,46080,46104,46080,46080,46080,46080,46080,46080,46080,46164,46080,46080,46080,46080,46080,46080,46080,46104,46080,46080,46272,46272,46368,46368,46416,46452,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47700,47616,47616,47616,47616,47616,47616,47616,47640,47616,47616,47616,47616,47616,47712,47760,47796,48384,48384,48384,48384,48384,48384,48384,48408,48384,48384,48384,48384,48384,48384,48432,48468,48768,48768,48768,48768,48768,48768,48768,48792,48960,48960,48960,48960,49056,49056,49104,49140,}; 43 | 44 | unsigned int PulseSaw_8580[4096] = { 45 | 0,0,0,0,0,0,0,36,0,0,0,12,0,0,48,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,168,180,0,0,0,12,0,0,0,84,0,0,0,36,0,48,168,180,0,0,0,12,0,0,48,84,192,192,288,324,336,336,360,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,288,336,360,372,0,0,0,12, 46 | 0,0,0,84,0,0,0,36,0,144,168,564,0,384,384,396,576,576,624,660,576,672,672,708,720,732,1512,1524,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,96,144,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,180,0,0,0,12,0,0,240,660,576,672,672,708,720,732,744,756,0,0,0,12,0,0,0,36, 47 | 0,0,0,36,0,0,168,180,0,0,0,12,0,0,0,84,0,0,288,324,288,336,1128,1140,0,768,768,780,768,768,768,1236,1152,1152,1152,1188,1248,1296,1320,1332,1152,1152,1344,1380,1344,1344,1416,1428,1440,1440,1440,3012,3024,3036,3048,3060,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,168,372,0,0,0,12,0,0,0,84,0,0,0,36, 48 | 0,48,168,180,0,0,0,12,0,0,48,276,192,192,288,708,720,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,324,288,336,360,372,0,0,0,12,0,0,0,84,0,0,0,420,384,528,1320,1332,1152,1152,1152,1356,1344,1344,1392,1428,1344,1440,1440,1476,1488,1500,1512,1524,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180, 49 | 0,0,0,12,0,0,0,84,0,0,0,132,96,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,180,0,0,0,396,384,576,624,660,576,672,672,2244,2256,2268,2280,2292,1536,1536,1536,1548,1536,1536,1536,1620,1536,1536,1536,1572,1536,1584,2472,2484,2304,2304,2304,2316,2304,2304,2352,2388,2304,2496,2592,2628,2640,2640,2664,2676,2304,2304,2304,2700,2688,2688,2688,2772,2688,2688,2688,2724,2784,5904,5928,6132,5760,5952,5952,5988, 50 | 5952,5952,6024,6132,6048,6048,6048,6084,6096,6108,6120,6132,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,168,372,0,0,0,12,0,0,0,84,0,0,0,36,0,48,168,180,0,0,0,12,0,0,48,276,192,192,288,324,336,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84, 51 | 0,0,0,324,288,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,528,552,564,384,384,384,588,576,576,1392,1428,1344,1440,1440,1476,1488,1500,1512,1524,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,96,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,180,0,0,0,12,0,576,624,660,576,672,672,708, 52 | 720,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,168,180,0,0,0,12,0,0,768,852,768,960,1056,2628,2592,2640,2664,2676,2304,2304,2304,2316,2304,2688,2688,2772,2688,2688,2688,2724,2784,2832,2856,2868,2688,2880,2880,2916,2880,2880,2952,2964,2976,2976,2976,3012,3024,3036,3048,3060,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,360,372, 53 | 0,0,0,12,0,0,0,84,0,0,0,36,0,48,168,180,0,0,0,12,0,0,240,276,192,576,672,708,720,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,192,324,288,336,360,372,0,0,0,12,0,0,768,852,768,1152,1152,1188,1152,4368,4392,4404,4224,4224,4416,4452,4416,4416,4488,4500,4416,4512,4512,4548,4560,4572,4584,4596,3072,3072,3072,3084, 54 | 3072,3072,3072,3108,3072,3072,3072,3108,3072,3072,3144,3252,3072,3072,3072,3084,3072,3072,3072,3156,3072,3072,3072,4740,4896,4944,4968,4980,4608,4608,4608,4620,4608,4608,4608,4692,4608,4608,4608,4644,4608,4752,4776,4788,4608,4992,4992,5004,5184,5184,5232,5268,11328,11424,11424,11460,11472,11484,11496,11508,10752,10752,10752,10764,10752,10752,11520,11604,11520,11520,11520,11556,11520,11568,11688,11700,11520,11520,11520,11532,11520,11520,11568,11604,11712,11712,11808,11844,11856,11868,11880,12276,11520,11904,11904,11916,11904,11904,11904,11988, 55 | 11904,11904,11904,11940,12000,12048,12072,12276,12096,12096,12096,12132,12096,12096,12168,12276,12192,12192,12192,12228,12240,12252,12264,12276,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,168,180,0,0,0,12,0,0,0,84,0,0,0,36,0,48,168,180,0,0,0,12,0,0,48,84,192,192,288,324,336,348,744,756,0,0,0,12,0,0,0,36,0,0,0,36, 56 | 0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,288,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,552,564,384,384,384,396,576,576,624,660,576,672,1440,1476,1488,1500,1512,1524,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,96,144,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,180, 57 | 0,0,0,12,0,0,624,660,576,672,672,708,720,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,168,180,0,0,0,12,0,0,0,84,0,0,1056,1092,1056,1104,1128,1140,768,768,768,780,768,768,1152,1236,1152,1152,1152,2724,2784,2832,2856,2868,2688,2688,2880,2916,2880,2880,2952,2964,2976,2976,2976,3012,3024,3036,3048,3060,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12, 58 | 0,0,0,84,0,0,0,36,96,144,168,372,0,0,0,12,0,0,0,84,0,0,0,36,0,48,168,180,0,0,0,12,0,0,48,276,192,192,672,708,720,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,324,288,336,360,372,0,0,0,12,0,0,0,84,0,0,1152,1188,1152,1296,1320,1332,1152,1152,1152,1356,1344,1344,1392,1428, 59 | 1344,1440,1440,1476,1488,1500,1512,1524,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,96,336,360,372,0,0,0,12,0,0,0,84,0,0,0,1572,1536,4752,4776,4788,4608,4608,4992,5004,4992,5184,5232,5268,5184,5280,5280,5316,5328,5340,5352,5364,4608,4608,4608,4620,4608,4608,4608,4692,4608,4608,5376,5412,5376,5424,5544,5556,5376,5376,5376,5388,5376,5376,5424,5460,5376,5568,5664,5700, 60 | 5712,5712,5736,5748,5376,5376,5760,5772,5760,5760,5760,5844,5760,5760,5760,5796,5856,5904,5928,6132,5760,5952,5952,5988,5952,5952,6024,6132,6048,6048,6048,6084,6096,6108,6120,6132,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,168,372,0,0,0,12,0,0,0,84,0,0,0,36,0,48,168,180,0,0,0,12,0,0,48,276,192,192,288,324,720,732,744,756, 61 | 0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,324,288,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,384,528,552,564,384,384,1152,1356,1344,1344,1392,1428,1344,1440,1440,1476,1488,1500,1512,1524,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,96,336,360,372,0,0,0,12, 62 | 0,0,0,84,0,0,0,36,0,144,168,180,0,0,0,12,384,576,624,660,6720,6816,6816,6852,6864,6876,6888,6900,6144,6144,6144,6156,6144,6144,6144,6180,6144,6144,6144,7716,7680,7680,7848,7860,7680,7680,8448,8460,8448,8448,8448,8532,8448,8640,8736,8772,8736,8784,8808,8820,8448,8448,8448,8460,8832,8832,8832,8916,8832,8832,8832,21156,21216,21264,21288,21300,21120,21312,21312,21348,21312,21312,21384,21396,21408,21408,21408,21444,21456,21468,21480,21492,6144,18432,18432,18432,18432,18432,18432,18468, 63 | 18432,18432,18432,18468,18432,18432,18504,18612,18432,18432,18432,18444,18432,18432,18432,18516,18432,18432,18432,18564,18528,18576,18792,18804,18432,18432,18432,18444,18432,18432,18432,18516,18432,18432,18432,18468,18432,21648,21672,21684,21504,21504,21504,21516,21504,21504,21744,21780,22080,22176,22176,22212,22224,22236,22248,22260,21504,21504,21504,21516,21504,21504,21504,21540,21504,21504,21504,21540,21504,21504,21672,21684,21504,21504,21504,21516,21504,21504,21504,21588,21504,21504,21792,21828,21792,21840,21864,21876,21504,21504,22272,22284,22272,22272,22272,22356,22656,22656,22656,22692, 64 | 22752,22800,22824,22836,22656,22656,22848,22884,22848,22848,22920,22932,22944,22944,22944,22980,22992,23004,23016,23028,21504,21504,21504,21516,21504,21504,21504,21540,21504,21504,21504,23076,23040,23040,23112,23220,23040,23040,23040,23052,23040,23040,23040,23124,23040,23040,23040,23172,23328,23376,23400,23412,23040,23040,23040,23052,23040,23040,23040,23124,23040,23040,23040,23076,23040,23184,23208,23604,23424,23424,23424,23436,23616,23616,23664,23700,23616,23712,23712,23748,23760,24540,24552,24564,23040,23040,23808,23820,23808,23808,23808,23892,23808,23808,23808,23844,23808,23856,23976,23988, 65 | 23808,23808,23808,23820,23808,23808,23856,24084,24000,24000,24096,24132,24144,24156,24552,24564,24192,24192,24192,24204,24192,24192,24192,24276,24192,24192,24192,24228,24288,24336,24360,24564,24384,24384,24384,24420,24384,24384,24456,24564,24480,24480,24480,24516,24528,24540,24552,24564,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,168,180,0,0,0,12,0,0,0,84,0,0,0,36,0,48,168,180,0,0,0,12, 66 | 0,0,48,84,192,192,288,324,336,336,360,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,288,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,564,384,384,384,396,576,576,624,660,576,672,672,708,1488,1500,1512,1524,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84, 67 | 0,0,0,132,96,144,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,180,0,0,0,12,0,0,240,660,576,672,672,708,720,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,168,180,0,0,0,12,0,0,0,84,0,0,288,324,1056,1104,1128,1140,768,768,768,780,768,768,768,1236,1152,1152,1152,1188,1248,1296,1320,1332,1152,1152,1344,2916,2880,2880,2952,2964,2976,2976,2976,3012, 68 | 3024,3036,3048,3060,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,168,372,0,0,0,12,0,0,0,84,0,0,0,36,0,48,168,180,0,0,0,12,0,0,48,276,192,192,288,708,720,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,324,288,336,360,372, 69 | 0,0,0,12,0,0,0,84,0,0,0,420,1152,1296,1320,1332,1152,1152,1152,1356,1344,1344,1392,1428,1344,1440,1440,1476,1488,1500,1512,1524,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,96,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,180,0,0,0,1932,1920,2112,2160,2196,2112,2208,2208,2244,2256,2268,2280,2292,1536,1536,1536,1548, 70 | 1536,1536,1536,1620,1536,1536,1536,1572,2304,5424,5544,5556,5376,5376,5376,5388,5376,5376,5424,5460,5376,5568,5664,5700,5712,5712,5736,5748,5376,5376,5376,5772,5760,5760,5760,5844,5760,5760,5760,5796,5856,5904,5928,6132,5760,5952,5952,5988,5952,5952,6024,6132,6048,6048,6048,6084,6096,6108,6120,6132,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,0,0,84,0,0,0,36,96,144,168,372,0,0,0,12,0,0,0,84, 71 | 0,0,0,36,0,48,168,180,0,0,0,12,0,0,48,276,192,192,288,324,336,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,324,288,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,528,552,564,384,384,384,588,1344,1344,1392,1428,1344,1440,1440,1476,1488,1500,1512,1524,0,0,0,12,0,0,0,36,0,0,0,36, 72 | 0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,96,336,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,180,0,0,0,12,0,576,624,660,576,672,672,708,720,732,744,756,0,0,0,12,0,0,0,36,0,0,0,36,0,0,168,180,0,0,0,1548,2304,2304,2304,2388,2304,2496,2592,2628,2592,2640,2664,2676,2304,2304,2304,2316,2304,2688,2688,2772,2688,2688,2688,2724,2784,2832,2856,2868, 73 | 2688,2880,2880,2916,2880,2880,2952,2964,2976,2976,2976,3012,3024,3036,3048,3060,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,180,0,0,0,12,0,0,0,84,0,0,0,132,96,144,360,372,0,0,0,12,0,0,0,84,0,0,0,36,0,144,168,180,0,0,0,12,0,0,240,276,6336,6816,6816,6852,6864,6876,6888,6900,6144,6144,6144,6156,6144,6144,6144,6180,6144,6144,6144,6180,6144,9216,9384,9396,9216,9216,9216,9228, 74 | 9216,9216,9216,9300,9216,9216,9504,9540,9504,9552,9576,9588,9216,9216,9216,9228,9984,9984,9984,10068,9984,10368,10368,10404,10464,10512,10536,10548,10368,10368,10560,10596,10560,10560,10632,10644,10656,10656,10656,10692,10704,10716,10728,10740,9216,9216,9216,9228,9216,9216,9216,9252,9216,9216,9216,9252,9216,9216,9288,9396,9216,9216,9216,10764,10752,10752,10752,10836,10752,10752,10752,10884,11040,11088,11112,11124,10752,10752,10752,10764,10752,10752,10752,10836,10752,10752,10752,10788,10752,10896,10920,10932,10752,11136,11136,11148,11328,11328,11376,11412, 75 | 11328,11424,11424,11460,36048,36060,36072,36852,10752,10752,35328,35340,36096,36096,36096,36180,36096,36096,36096,36132,36096,36144,36264,36276,36096,36096,36096,36108,36096,36096,36144,36372,36288,36288,36384,36420,36432,36444,36840,36852,36096,36480,36480,36492,36480,36480,36480,36564,36480,36480,36480,36516,36576,36624,36648,36852,36672,36672,36672,36708,36672,36672,36744,36852,36768,36768,36768,36804,36816,36828,36840,36852,0,0,0,0,0,0,0,36,0,0,0,36,0,0,72,84,0,0,0,12,0,24576,24576,24660,24576,24576,24576,24612, 76 | 24672,24720,24744,24948,24576,24576,24576,24588,24576,24576,24576,24660,24576,24576,24576,24612,24576,24624,24744,24756,24576,24576,24576,24588,24576,24576,24624,24852,24768,24768,24864,24900,24912,24924,25320,25332,24576,24576,24576,24588,24576,24576,24576,24612,24576,24576,24576,24612,24576,24576,24648,24756,24576,24576,24576,24588,24576,24576,24576,24660,24576,24576,24576,24900,24864,24912,24936,24948,24576,24576,24576,24588,24576,24576,24576,24660,24576,24576,24576,24612,24576,24720,25128,25140,24960,24960,24960,25164,25152,25152,25200,25236,25920,26016,26016,26052,26064,26076,26088,26100, 77 | 24576,24576,24576,24576,24576,24576,24576,24612,24576,24576,24576,24612,24576,24576,24648,24756,24576,24576,24576,24588,24576,24576,24576,24660,24576,24576,24576,24708,24672,24912,24936,24948,24576,24576,24576,24588,24576,24576,24576,24660,24576,24576,24576,24612,24576,24720,24744,24756,24576,24576,24576,24588,24576,24768,25200,25236,25152,25248,25248,25284,25296,25308,25320,25332,24576,24576,24576,24588,24576,24576,24576,24612,24576,24576,24576,24612,24576,24576,24744,24756,24576,24576,24576,24588,24576,24576,24576,24660,25344,25536,25632,25668,25632,25680,25704,25716,25344,25344,25344,26892, 78 | 26880,26880,27264,27348,27264,27264,27264,39588,39648,39696,39720,39732,39552,39744,39744,39780,39744,39744,39816,39828,39840,39840,39840,39876,39888,39900,39912,39924,24576,36864,36864,36864,36864,36864,36864,36900,36864,36864,36864,36900,36864,36864,36936,36948,36864,36864,36864,36876,36864,36864,36864,36948,36864,36864,36864,36900,36960,37008,37224,37236,36864,36864,36864,36876,36864,36864,36864,36948,36864,36864,36864,36900,36864,36912,37032,37044,36864,36864,36864,36876,36864,36864,37104,37140,37056,37056,37536,37572,37584,37596,37608,37620,36864,36864,36864,36876,36864,36864,36864,36900, 79 | 36864,36864,36864,36900,36864,36864,36936,37044,36864,36864,36864,36876,36864,36864,36864,36948,36864,36864,37056,37188,37152,37200,37224,37236,36864,36864,36864,36876,36864,36864,36864,36948,37632,37632,38016,38052,38016,38160,38184,38196,38016,38016,38208,38244,38208,38208,38280,38292,38208,38304,38304,38340,38352,38364,38376,38388,36864,36864,36864,36876,36864,36864,36864,36900,36864,36864,36864,36900,36864,39936,40008,40116,39936,39936,39936,39948,39936,39936,39936,40020,39936,39936,39936,40068,40224,40272,40296,40308,39936,39936,39936,41484,41472,41472,41472,41556,41472,41472,41472,41508, 80 | 41472,41616,41640,41652,41472,41472,41856,41868,42048,42048,42096,42132,42048,42144,42144,42180,42192,42204,42216,42228,41472,41472,41472,41484,41472,41472,41472,41556,42240,42240,42240,42276,42240,42288,42408,42420,42240,42240,42240,42252,42240,42240,42288,42324,42432,42432,42528,42564,42576,42576,42600,42996,42240,42240,42624,42636,42624,42624,42624,42708,42624,42624,42624,42660,42720,42768,42792,42996,42816,42816,42816,42852,42816,42816,42888,42996,42912,42912,42912,42948,42960,42972,42984,42996,36864,36864,36864,36864,36864,36864,36864,36900,36864,36864,36864,36900,36864,36864,36936,36948, 81 | 36864,36864,36864,36876,36864,36864,36864,36948,36864,36864,36864,36900,36960,37008,37032,37236,36864,36864,36864,36876,36864,36864,36864,36948,36864,36864,36864,36900,36864,36912,37032,37044,36864,36864,36864,36876,36864,36864,36912,37140,43200,43200,43296,43332,43728,43740,43752,43764,43008,43008,43008,43020,43008,43008,43008,43044,43008,43008,43008,43044,43008,43008,43080,43188,43008,43008,43008,43020,43008,43008,43008,43092,43008,43008,43008,43332,43296,43344,43368,43380,43008,43008,43008,43020,43008,43008,43008,43092,43008,43008,43008,43044,43392,43536,43560,44340,44160,44160,44160,44364, 82 | 44352,44352,44400,44436,44352,44448,44448,44484,44496,44508,44520,44532,43008,43008,43008,43020,43008,43008,43008,43044,43008,43008,43008,43044,43008,43008,43080,43188,43008,43008,43008,43020,43008,43008,43008,43092,43008,43008,43008,43140,43104,43344,43368,43380,43008,43008,43008,43020,43008,43008,43008,43092,43008,43008,43008,43044,43008,43152,43176,43188,43008,43008,43008,43020,43392,43584,43632,43668,43584,43680,43680,43716,43728,45276,45288,45300,43008,43008,43008,44556,44544,44544,44544,44580,44544,44544,44544,44580,44544,44544,44712,45492,45312,45312,45312,45324,45312,45312,45312,45396, 83 | 45312,45504,45600,45636,45600,45648,45672,45684,45312,45312,45312,45324,45696,45696,45696,45780,45696,45696,45696,45732,45792,45840,45864,45876,45696,45888,45888,45924,45888,45888,45960,49140,49056,49056,49056,49092,49104,49116,49128,49140,43008,43008,43008,43008,43008,43008,43008,43044,43008,43008,43008,43044,43008,46080,46152,46260,46080,46080,46080,46092,46080,46080,46080,46164,46080,46080,46080,46212,46176,46224,46440,46452,46080,46080,46080,46092,46080,46080,46080,46164,46080,46080,46080,46116,46080,46224,46248,46260,46080,46080,46080,46092,46080,46080,46320,46740,46656,46752,46752,46788, 84 | 46800,46812,46824,46836,46080,46080,46080,46092,46080,46080,46080,46116,46080,46080,46080,46116,46080,46080,46248,46260,46080,46080,46080,46092,46080,46080,46080,46164,46080,46080,46368,46404,46368,46416,47208,47220,46848,46848,46848,46860,46848,46848,46848,47316,47232,47232,47232,47268,47328,47376,47400,47412,47232,47232,47424,47460,47424,47424,47496,47508,49056,49056,49056,49092,49104,49116,49128,49140,46080,46080,46080,47628,47616,47616,47616,47652,47616,47616,47616,47652,47616,47616,47688,47796,47616,47616,47616,47628,47616,47616,47616,47700,47616,47616,47616,47748,47904,47952,47976,47988, 85 | 47616,47616,47616,47628,47616,47616,47616,47700,47616,47616,47616,47652,47616,47760,47784,48180,48000,48000,48000,48012,48192,48192,48240,48276,48192,48288,48288,49092,49104,49116,49128,49140,48384,48384,48384,48396,48384,48384,48384,48468,48384,48384,48384,48420,48384,48432,48552,48564,48384,48384,48384,48396,48384,48384,48432,48660,48576,48576,48672,48708,48720,49116,49128,49140,48768,48768,48768,48780,48768,48768,48768,48852,48768,48768,48768,48804,48864,48912,48936,49140,48960,48960,48960,48996,48960,48960,49032,49140,49056,49056,49056,49092,49104,49116,49128,49140,}; 86 | 87 | unsigned int PulseTriSaw_8580[4096] = { 88 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0, 89 | 0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,192,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0, 90 | 0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0, 91 | 0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,408,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72, 92 | 0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,1536,2304,2304,2304,2304,2304,2304,2328,2304,2304,2304,2304,2304,2304,2304,2388,2688,2688,2688,2688, 93 | 2688,2688,2688,2712,2880,2880,2880,2880,2976,2976,3024,3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24, 94 | 0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192, 95 | 288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,768,852,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180, 96 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,384,384,408,576,576,576,576,672,672,720,756,0,0,0,0, 97 | 0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,192,192,288,288,336,372,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4680,4608,4608,4608,4608,4608,4608,4608,4632,4608,4608,4608,4608,4608,4704,4752,4788,5376,5376,5376,5376,5376,5376,5376,5400, 98 | 5376,5376,5376,5376,5376,5376,5376,5460,5760,5760,5760,5760,5760,5760,5760,5784,5952,5952,5952,5952,6048,6048,6096,6132,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0, 99 | 0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84, 100 | 0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0, 101 | 0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,384,408, 102 | 576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,192,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,1536,1536, 103 | 1536,1632,1680,1716,2304,2304,2304,2304,2304,2304,2304,2328,2304,2304,2304,2304,2304,2304,2304,2388,2688,2688,2688,2688,2688,2688,2688,2712,2880,2880,2880,2880,2976,2976,3024,3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372, 104 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0, 105 | 0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,768,768,768,768,768,852,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0, 106 | 0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0, 107 | 0,0,0,84,0,0,0,0,384,384,384,408,576,576,576,576,672,672,720,756,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9288,9216,9216,9216,9216,9216,9216,9216,9240,9216,9216,9216,9216,9216,9216,9360,9396,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9216,9300,9216,9216,9216,9216,9216,9216,9216,9240,9216,9216,9408,9408,9504,9504,9552,9588,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10752,10824, 108 | 10752,10752,10752,10752,10752,10752,10752,10776,10752,10752,10752,10752,10752,10848,10896,10932,11520,11520,11520,11520,11520,11520,11520,11544,11520,11520,11520,11520,11520,11520,11520,11604,11904,11904,11904,11904,11904,11904,11904,11928,12096,12096,12096,12096,12192,12192,12240,12276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0, 109 | 0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24, 110 | 0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344, 111 | 1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180, 112 | 0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,408,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0, 113 | 0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,2304,2304,2304,2304,2304,2304,2304,2328,2304,2304,2304,2304,2304,2304,2304,2388,2688,2688,2688,2688,2688,2688,2688,2712,2880,2880,2880,2880,2976,2976,3024,3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0, 114 | 0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0, 115 | 0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0,0,0,0,24,0,0,0,0,768,768,768,852, 116 | 1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0, 117 | 0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,384,384,408,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,3072,3072,3072,3072,3072,3072,3072,3096, 118 | 3072,3072,3264,3264,3360,3360,3408,3444,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4608,4680,4608,4608,4608,4608,4608,4608,4608,4632,4608,4608,4608,4608,4608,4704,4752,4788,5376,5376,5376,5376,5376,5376,5376,5400,5376,5376,5376,5376,5376,5376,5376,5460,5760,5760,5760,5760,5760,5760,5760,5784,5952,5952,5952,5952,6048,6048,6096,6132,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0, 119 | 0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,576,576,576,576,672,672,720,756, 120 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,96,144,180,0,0,0,0, 121 | 0,0,0,24,0,0,0,0,0,0,0,84,1152,1152,1152,1152,1152,1152,1152,1176,1344,1344,1344,1344,1440,1440,1488,1524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0, 122 | 0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,84,0,0,0,0,0,0,384,408,576,576,576,576,672,672,720,756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0, 123 | 0,0,0,84,0,0,0,0,0,0,0,24,0,0,192,192,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,1536,1536,1536,1536,1536,1560,1536,1536,1536,1536,1536,1632,1680,1716,2304,2304,2304,2304,2304,2304,2304,2328,2304,2304,2304,2304,2304,2304,2304,2388,2688,2688,2688,2688,2688,2688,2688,2712,2880,2880,2880,2880,2976,2976,3024,3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72, 124 | 0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,24,0,0,0,0,288,288,336,372,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,24,0,0,0,0,0,0,144,180,12288,12288,12288,12288,12288,12288,12288,12312,12288,12288,12288,12288,12288,12288,12288,12372,12288,12288,12288,12288, 125 | 12288,12288,12288,12312,12864,12864,12864,12864,12960,12960,13008,13044,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12360,12288,12288,12288,12288,12288,12288,12288,12312,12288,12288,12288,12288,12288,12288,12432,12468,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12372,12288,12288,12288,12288,12288,12288,12288,12312,12288,12288,12288,12480,12576,12576,12624,12660,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12288,12360,12288,12288,12288,12288,12288,12288,12288,12312, 126 | 12288,12288,12288,12288,12288,12384,12432,12468,12288,12288,12288,12288,12288,12288,12288,12312,13056,13056,13056,13056,13056,13056,13056,13140,13440,13440,13440,13440,13440,13440,13440,13464,13632,13632,13632,13632,13728,13728,13776,13812,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18504,18432,18432,18432,18432,18432,18432,18432,18456,18432,18432,18432,18432,18432,18432,18576,18612,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18516,18432,18432,18432,18432,18432,18432,18432,18456,18432,18432,18432,18432, 127 | 18720,18720,18768,18804,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43008,43080,43008,43008,43008,43008,43008,43008,43008,43032,43008,43008,43008,43008,43008,43008,43152,43188,43008,43008,43008,43008,43008,43008,43008,43032,43008,43008,43008,43008,43008,43008,43008,43092,43008,43008,43008,43008,43392,43392,43392,43416,43584,43584,43584,43584,43680,43680,43728,43764,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46152,46080,46080,46080,46080,46080,46080,46080,46104,46080,46080,46080,46080,46080,46080,46224,46260, 128 | 46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46080,46164,46080,46080,46080,46080,46080,46080,46080,46104,46080,46080,46272,46272,46368,46368,46416,46452,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47616,47688,47616,47616,47616,47616,47616,47616,47616,47640,47616,47616,47616,47616,47616,47712,47760,47796,48384,48384,48384,48384,48384,48384,48384,48408,48384,48384,48384,48384,48384,48384,48384,48468,48768,48768,48768,48768,48768,48768,48768,48792,48960,48960,48960,48960,49056,49056,49104,49140,}; 129 | 130 | -------------------------------------------------------------------------------- /main/ssd1306.c: -------------------------------------------------------------------------------- 1 | #include "ssd1306.h" 2 | 3 | #define ABS(x) ((x) > 0 ? (x) : -(x)) 4 | 5 | /* SSD1306 data buffer */ 6 | static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8]; 7 | 8 | /* Private SSD1306 structure */ 9 | typedef struct { 10 | uint16_t CurrentX; 11 | uint16_t CurrentY; 12 | uint8_t Inverted; 13 | uint8_t Initialized; 14 | } SSD1306_t; 15 | 16 | /* Private variable */ 17 | static SSD1306_t SSD1306; 18 | 19 | uint8_t SSD1306_Init(void) { 20 | /* Init LCD */ 21 | SSD1306_WRITECOMMAND(0xAE); //display off 22 | SSD1306_WRITECOMMAND(0x20); //Set Memory Addressing Mode 23 | SSD1306_WRITECOMMAND(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid 24 | SSD1306_WRITECOMMAND(0xB0); //Set Page Start Address for Page Addressing Mode,0-7 25 | SSD1306_WRITECOMMAND(0xC8); //Set COM Output Scan DirectionSSD1306_WRITECOMMAND(command) 26 | SSD1306_WRITECOMMAND(0x00); //---set low column address 27 | SSD1306_WRITECOMMAND(0x10); //---set high column address 28 | SSD1306_WRITECOMMAND(0x40); //--set start line address 29 | SSD1306_WRITECOMMAND(0x81); //--set contrast control register 30 | SSD1306_WRITECOMMAND(0xFF); 31 | SSD1306_WRITECOMMAND(0xA1); //--set segment re-map 0 to 127 32 | SSD1306_WRITECOMMAND(0xA6); //--set normal display 33 | SSD1306_WRITECOMMAND(0xA8); //--set multiplex ratio(1 to 64) 34 | SSD1306_WRITECOMMAND(0x3F); // 35 | SSD1306_WRITECOMMAND(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content 36 | SSD1306_WRITECOMMAND(0xD3); //-set display offset 37 | SSD1306_WRITECOMMAND(0x00); //-not offset 38 | SSD1306_WRITECOMMAND(0xD5); //--set display clock divide ratio/oscillator frequency 39 | SSD1306_WRITECOMMAND(0xF0); //--set divide ratio 40 | SSD1306_WRITECOMMAND(0xD9); //--set pre-charge period 41 | SSD1306_WRITECOMMAND(0x22); // 42 | SSD1306_WRITECOMMAND(0xDA); //--set com pins hardware configuration 43 | SSD1306_WRITECOMMAND(0x12); 44 | SSD1306_WRITECOMMAND(0xDB); //--set vcomh 45 | SSD1306_WRITECOMMAND(0x20); //0x20,0.77xVcc 46 | SSD1306_WRITECOMMAND(0x8D); //--set DC-DC enable 47 | SSD1306_WRITECOMMAND(0x14); // 48 | SSD1306_WRITECOMMAND(0xAF); //--turn on SSD1306 panel 49 | 50 | /* Clear screen */ 51 | SSD1306_Fill(SSD1306_COLOR_BLACK); 52 | 53 | /* Update screen */ 54 | SSD1306_UpdateScreen(); 55 | 56 | /* Set default values */ 57 | SSD1306.CurrentX = 0; 58 | SSD1306.CurrentY = 0; 59 | 60 | /* Initialized OK */ 61 | SSD1306.Initialized = 1; 62 | 63 | /* Return OK */ 64 | return 1; 65 | } 66 | 67 | void SSD1306_UpdateScreen(void) { 68 | uint8_t m; 69 | int ret; 70 | for (m = 0; m < 8; m++) { 71 | SSD1306_WRITECOMMAND(0xB0 + m); 72 | SSD1306_WRITECOMMAND(0x00); 73 | SSD1306_WRITECOMMAND(0x10); 74 | 75 | // Write multi data 76 | ret = X_WriteMulti(I2C_NUM_1,0x3C,0x40,SSD1306_WIDTH, &SSD1306_Buffer[SSD1306_WIDTH * m]); 77 | if (ret == ESP_FAIL) { 78 | printf("I2C Fail\n"); 79 | } 80 | 81 | } 82 | } 83 | 84 | void SSD1306_ToggleInvert(void) { 85 | uint16_t i; 86 | 87 | /* Toggle invert */ 88 | SSD1306.Inverted = !SSD1306.Inverted; 89 | 90 | /* Do memory toggle */ 91 | for (i = 0; i < sizeof(SSD1306_Buffer); i++) { 92 | SSD1306_Buffer[i] = ~SSD1306_Buffer[i]; 93 | } 94 | } 95 | 96 | void SSD1306_Fill(SSD1306_COLOR_t color) { 97 | /* Set memory */ 98 | memset(SSD1306_Buffer, (color == SSD1306_COLOR_BLACK) ? 0x00 : 0xFF, sizeof(SSD1306_Buffer)); 99 | } 100 | 101 | void SSD1306_DrawPixel(uint16_t x, uint16_t y, SSD1306_COLOR_t color) { 102 | if ( 103 | x >= SSD1306_WIDTH || 104 | y >= SSD1306_HEIGHT 105 | ) { 106 | /* Error */ 107 | return; 108 | } 109 | 110 | /* Check if pixels are inverted */ 111 | if (SSD1306.Inverted) { 112 | color = (SSD1306_COLOR_t)!color; 113 | } 114 | 115 | /* Set color */ 116 | if (color == SSD1306_COLOR_WHITE) { 117 | SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8); 118 | } else { 119 | SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8)); 120 | } 121 | } 122 | 123 | void SSD1306_GotoXY(uint16_t x, uint16_t y) { 124 | /* Set write pointers */ 125 | SSD1306.CurrentX = x; 126 | SSD1306.CurrentY = y; 127 | } 128 | 129 | char SSD1306_Putc(char ch, FontDef_t* Font, SSD1306_COLOR_t color) { 130 | uint32_t i, b, j; 131 | 132 | /* Check available space in LCD */ 133 | if ( 134 | SSD1306_WIDTH <= (SSD1306.CurrentX + Font->FontWidth) || 135 | SSD1306_HEIGHT <= (SSD1306.CurrentY + Font->FontHeight) 136 | ) { 137 | /* Error */ 138 | return 0; 139 | } 140 | 141 | /* Go through font */ 142 | for (i = 0; i < Font->FontHeight; i++) { 143 | b = Font->data[(ch - 32) * Font->FontHeight + i]; 144 | for (j = 0; j < Font->FontWidth; j++) { 145 | if ((b << j) & 0x8000) { 146 | SSD1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR_t) color); 147 | } else { 148 | SSD1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR_t)!color); 149 | } 150 | } 151 | } 152 | 153 | /* Increase pointer */ 154 | SSD1306.CurrentX += Font->FontWidth; 155 | 156 | /* Return character written */ 157 | return ch; 158 | } 159 | 160 | char SSD1306_Puts(char* str, FontDef_t* Font, SSD1306_COLOR_t color) { 161 | /* Write characters */ 162 | while (*str) { 163 | /* Write character by character */ 164 | if (SSD1306_Putc(*str, Font, color) != *str) { 165 | /* Return error */ 166 | return *str; 167 | } 168 | 169 | /* Increase string pointer */ 170 | str++; 171 | } 172 | 173 | /* Everything OK, zero should be returned */ 174 | return *str; 175 | } 176 | 177 | 178 | void SSD1306_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, SSD1306_COLOR_t c) { 179 | int16_t dx, dy, sx, sy, err, e2, i, tmp; 180 | 181 | /* Check for overflow */ 182 | if (x0 >= SSD1306_WIDTH) { 183 | x0 = SSD1306_WIDTH - 1; 184 | } 185 | if (x1 >= SSD1306_WIDTH) { 186 | x1 = SSD1306_WIDTH - 1; 187 | } 188 | if (y0 >= SSD1306_HEIGHT) { 189 | y0 = SSD1306_HEIGHT - 1; 190 | } 191 | if (y1 >= SSD1306_HEIGHT) { 192 | y1 = SSD1306_HEIGHT - 1; 193 | } 194 | 195 | dx = (x0 < x1) ? (x1 - x0) : (x0 - x1); 196 | dy = (y0 < y1) ? (y1 - y0) : (y0 - y1); 197 | sx = (x0 < x1) ? 1 : -1; 198 | sy = (y0 < y1) ? 1 : -1; 199 | err = ((dx > dy) ? dx : -dy) / 2; 200 | 201 | if (dx == 0) { 202 | if (y1 < y0) { 203 | tmp = y1; 204 | y1 = y0; 205 | y0 = tmp; 206 | } 207 | 208 | if (x1 < x0) { 209 | tmp = x1; 210 | x1 = x0; 211 | x0 = tmp; 212 | } 213 | 214 | /* Vertical line */ 215 | for (i = y0; i <= y1; i++) { 216 | SSD1306_DrawPixel(x0, i, c); 217 | } 218 | 219 | /* Return from function */ 220 | return; 221 | } 222 | 223 | if (dy == 0) { 224 | if (y1 < y0) { 225 | tmp = y1; 226 | y1 = y0; 227 | y0 = tmp; 228 | } 229 | 230 | if (x1 < x0) { 231 | tmp = x1; 232 | x1 = x0; 233 | x0 = tmp; 234 | } 235 | 236 | /* Horizontal line */ 237 | for (i = x0; i <= x1; i++) { 238 | SSD1306_DrawPixel(i, y0, c); 239 | } 240 | 241 | /* Return from function */ 242 | return; 243 | } 244 | 245 | while (1) { 246 | SSD1306_DrawPixel(x0, y0, c); 247 | if (x0 == x1 && y0 == y1) { 248 | break; 249 | } 250 | e2 = err; 251 | if (e2 > -dx) { 252 | err -= dy; 253 | x0 += sx; 254 | } 255 | if (e2 < dy) { 256 | err += dx; 257 | y0 += sy; 258 | } 259 | } 260 | } 261 | 262 | void SSD1306_DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c) { 263 | /* Check input parameters */ 264 | if ( 265 | x >= SSD1306_WIDTH || 266 | y >= SSD1306_HEIGHT 267 | ) { 268 | /* Return error */ 269 | return; 270 | } 271 | 272 | /* Check width and height */ 273 | if ((x + w) >= SSD1306_WIDTH) { 274 | w = SSD1306_WIDTH - x; 275 | } 276 | if ((y + h) >= SSD1306_HEIGHT) { 277 | h = SSD1306_HEIGHT - y; 278 | } 279 | 280 | /* Draw 4 lines */ 281 | SSD1306_DrawLine(x, y, x + w, y, c); /* Top line */ 282 | SSD1306_DrawLine(x, y + h, x + w, y + h, c); /* Bottom line */ 283 | SSD1306_DrawLine(x, y, x, y + h, c); /* Left line */ 284 | SSD1306_DrawLine(x + w, y, x + w, y + h, c); /* Right line */ 285 | } 286 | 287 | void SSD1306_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c) { 288 | uint8_t i; 289 | 290 | /* Check input parameters */ 291 | if ( 292 | x >= SSD1306_WIDTH || 293 | y >= SSD1306_HEIGHT 294 | ) { 295 | /* Return error */ 296 | return; 297 | } 298 | 299 | /* Check width and height */ 300 | if ((x + w) >= SSD1306_WIDTH) { 301 | w = SSD1306_WIDTH - x; 302 | } 303 | if ((y + h) >= SSD1306_HEIGHT) { 304 | h = SSD1306_HEIGHT - y; 305 | } 306 | 307 | /* Draw lines */ 308 | for (i = 0; i <= h; i++) { 309 | /* Draw lines */ 310 | SSD1306_DrawLine(x, y + i, x + w, y + i, c); 311 | } 312 | } 313 | 314 | void SSD1306_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color) { 315 | /* Draw lines */ 316 | SSD1306_DrawLine(x1, y1, x2, y2, color); 317 | SSD1306_DrawLine(x2, y2, x3, y3, color); 318 | SSD1306_DrawLine(x3, y3, x1, y1, color); 319 | } 320 | 321 | 322 | void SSD1306_DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color) { 323 | int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 324 | yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0, 325 | curpixel = 0; 326 | 327 | deltax = ABS(x2 - x1); 328 | deltay = ABS(y2 - y1); 329 | x = x1; 330 | y = y1; 331 | 332 | if (x2 >= x1) { 333 | xinc1 = 1; 334 | xinc2 = 1; 335 | } else { 336 | xinc1 = -1; 337 | xinc2 = -1; 338 | } 339 | 340 | if (y2 >= y1) { 341 | yinc1 = 1; 342 | yinc2 = 1; 343 | } else { 344 | yinc1 = -1; 345 | yinc2 = -1; 346 | } 347 | 348 | if (deltax >= deltay){ 349 | xinc1 = 0; 350 | yinc2 = 0; 351 | den = deltax; 352 | num = deltax / 2; 353 | numadd = deltay; 354 | numpixels = deltax; 355 | } else { 356 | xinc2 = 0; 357 | yinc1 = 0; 358 | den = deltay; 359 | num = deltay / 2; 360 | numadd = deltax; 361 | numpixels = deltay; 362 | } 363 | 364 | for (curpixel = 0; curpixel <= numpixels; curpixel++) { 365 | SSD1306_DrawLine(x, y, x3, y3, color); 366 | 367 | num += numadd; 368 | if (num >= den) { 369 | num -= den; 370 | x += xinc1; 371 | y += yinc1; 372 | } 373 | x += xinc2; 374 | y += yinc2; 375 | } 376 | } 377 | 378 | void SSD1306_DrawCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c) { 379 | int16_t f = 1 - r; 380 | int16_t ddF_x = 1; 381 | int16_t ddF_y = -2 * r; 382 | int16_t x = 0; 383 | int16_t y = r; 384 | 385 | SSD1306_DrawPixel(x0, y0 + r, c); 386 | SSD1306_DrawPixel(x0, y0 - r, c); 387 | SSD1306_DrawPixel(x0 + r, y0, c); 388 | SSD1306_DrawPixel(x0 - r, y0, c); 389 | 390 | while (x < y) { 391 | if (f >= 0) { 392 | y--; 393 | ddF_y += 2; 394 | f += ddF_y; 395 | } 396 | x++; 397 | ddF_x += 2; 398 | f += ddF_x; 399 | 400 | SSD1306_DrawPixel(x0 + x, y0 + y, c); 401 | SSD1306_DrawPixel(x0 - x, y0 + y, c); 402 | SSD1306_DrawPixel(x0 + x, y0 - y, c); 403 | SSD1306_DrawPixel(x0 - x, y0 - y, c); 404 | 405 | SSD1306_DrawPixel(x0 + y, y0 + x, c); 406 | SSD1306_DrawPixel(x0 - y, y0 + x, c); 407 | SSD1306_DrawPixel(x0 + y, y0 - x, c); 408 | SSD1306_DrawPixel(x0 - y, y0 - x, c); 409 | } 410 | } 411 | 412 | void SSD1306_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c) { 413 | int16_t f = 1 - r; 414 | int16_t ddF_x = 1; 415 | int16_t ddF_y = -2 * r; 416 | int16_t x = 0; 417 | int16_t y = r; 418 | 419 | SSD1306_DrawPixel(x0, y0 + r, c); 420 | SSD1306_DrawPixel(x0, y0 - r, c); 421 | SSD1306_DrawPixel(x0 + r, y0, c); 422 | SSD1306_DrawPixel(x0 - r, y0, c); 423 | SSD1306_DrawLine(x0 - r, y0, x0 + r, y0, c); 424 | 425 | while (x < y) { 426 | if (f >= 0) { 427 | y--; 428 | ddF_y += 2; 429 | f += ddF_y; 430 | } 431 | x++; 432 | ddF_x += 2; 433 | f += ddF_x; 434 | 435 | SSD1306_DrawLine(x0 - x, y0 + y, x0 + x, y0 + y, c); 436 | SSD1306_DrawLine(x0 + x, y0 - y, x0 - x, y0 - y, c); 437 | 438 | SSD1306_DrawLine(x0 + y, y0 + x, x0 - y, y0 + x, c); 439 | SSD1306_DrawLine(x0 + y, y0 - x, x0 - y, y0 - x, c); 440 | } 441 | } 442 | 443 | void SSD1306_ON(void) { 444 | SSD1306_WRITECOMMAND(0x8D); 445 | SSD1306_WRITECOMMAND(0x14); 446 | SSD1306_WRITECOMMAND(0xAF); 447 | } 448 | void SSD1306_OFF(void) { 449 | SSD1306_WRITECOMMAND(0x8D); 450 | SSD1306_WRITECOMMAND(0x10); 451 | SSD1306_WRITECOMMAND(0xAE); 452 | } 453 | 454 | void SSD1306_WRITECOMMAND(uint8_t command) 455 | { 456 | int ret; 457 | ret = X_WrByte(I2C_NUM_1,0x3C,0x00,command); 458 | if (ret == ESP_FAIL) { 459 | printf("I2C Fail\n"); 460 | } 461 | 462 | } 463 | -------------------------------------------------------------------------------- /main/ssd1306.h: -------------------------------------------------------------------------------- 1 | #ifndef SSD1306_H 2 | #define SSD1306_H 3 | 4 | #include "driver/i2c.h" 5 | #include "xi2c.h" 6 | #include "fonts.h" 7 | #include "stdlib.h" 8 | #include "string.h" 9 | #include "esp_system.h" 10 | 11 | /* I2C address */ 12 | #ifndef SSD1306_I2C_ADDR 13 | #define SSD1306_I2C_ADDR 0x3C//0x78 14 | /* Use defines.h for custom definitions */ 15 | //#define SSD1306_I2C_ADDR 0x7A 16 | #endif 17 | 18 | /* SSD1306 settings */ 19 | /* SSD1306 width in pixels */ 20 | #ifndef SSD1306_WIDTH 21 | #define SSD1306_WIDTH 132 22 | #endif 23 | /* SSD1306 LCD height in pixels */ 24 | #ifndef SSD1306_HEIGHT 25 | #define SSD1306_HEIGHT 64 26 | #endif 27 | 28 | /** 29 | * @brief SSD1306 color enumeration 30 | */ 31 | 32 | typedef enum { 33 | SSD1306_COLOR_BLACK = 0x00, /*!< Black color, no pixel */ 34 | SSD1306_COLOR_WHITE = 0x01 /*!< Pixel is set. Color depends on LCD */ 35 | } SSD1306_COLOR_t; 36 | 37 | /** 38 | * @brief Initializes SSD1306 39 | * @param None 40 | * @retval Initialization status: 41 | * - 0: SSD1306 was not detected on I2C port 42 | * - >0: SSD1306 initialized OK and ready to use 43 | */ 44 | uint8_t SSD1306_Init(void); 45 | 46 | /** 47 | * @brief Updates buffer from internal RAM to LCD 48 | * @note This function must be called each time you do some changes to LCD, to update buffer from RAM to LCD 49 | * @param None 50 | * @retval None 51 | */ 52 | void SSD1306_UpdateScreen(void); 53 | 54 | /** 55 | * @brief Toggles pixels invertion inside internal RAM 56 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 57 | * @param None 58 | * @retval None 59 | */ 60 | void SSD1306_ToggleInvert(void); 61 | 62 | /** 63 | * @brief Fills entire LCD with desired color 64 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 65 | * @param Color: Color to be used for screen fill. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 66 | * @retval None 67 | */ 68 | void SSD1306_Fill(SSD1306_COLOR_t Color); 69 | 70 | /** 71 | * @brief Draws pixel at desired location 72 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 73 | * @param x: X location. This parameter can be a value between 0 and SSD1306_WIDTH - 1 74 | * @param y: Y location. This parameter can be a value between 0 and SSD1306_HEIGHT - 1 75 | * @param color: Color to be used for screen fill. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 76 | * @retval None 77 | */ 78 | void SSD1306_DrawPixel(uint16_t x, uint16_t y, SSD1306_COLOR_t color); 79 | 80 | /** 81 | * @brief Sets cursor pointer to desired location for strings 82 | * @param x: X location. This parameter can be a value between 0 and SSD1306_WIDTH - 1 83 | * @param y: Y location. This parameter can be a value between 0 and SSD1306_HEIGHT - 1 84 | * @retval None 85 | */ 86 | void SSD1306_GotoXY(uint16_t x, uint16_t y); 87 | 88 | /** 89 | * @brief Puts character to internal RAM 90 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 91 | * @param ch: Character to be written 92 | * @param *Font: Pointer to @ref FontDef_t structure with used font 93 | * @param color: Color used for drawing. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 94 | * @retval Character written 95 | */ 96 | char SSD1306_Putc(char ch, FontDef_t* Font, SSD1306_COLOR_t color); 97 | 98 | /** 99 | * @brief Puts string to internal RAM 100 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 101 | * @param *str: String to be written 102 | * @param *Font: Pointer to @ref FontDef_t structure with used font 103 | * @param color: Color used for drawing. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 104 | * @retval Zero on success or character value when function failed 105 | */ 106 | char SSD1306_Puts(char* str, FontDef_t* Font, SSD1306_COLOR_t color); 107 | 108 | /** 109 | * @brief Draws line on LCD 110 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 111 | * @param x0: Line X start point. Valid input is 0 to SSD1306_WIDTH - 1 112 | * @param y0: Line Y start point. Valid input is 0 to SSD1306_HEIGHT - 1 113 | * @param x1: Line X end point. Valid input is 0 to SSD1306_WIDTH - 1 114 | * @param y1: Line Y end point. Valid input is 0 to SSD1306_HEIGHT - 1 115 | * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 116 | * @retval None 117 | */ 118 | void SSD1306_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, SSD1306_COLOR_t c); 119 | 120 | /** 121 | * @brief Draws rectangle on LCD 122 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 123 | * @param x: Top left X start point. Valid input is 0 to SSD1306_WIDTH - 1 124 | * @param y: Top left Y start point. Valid input is 0 to SSD1306_HEIGHT - 1 125 | * @param w: Rectangle width in units of pixels 126 | * @param h: Rectangle height in units of pixels 127 | * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 128 | * @retval None 129 | */ 130 | void SSD1306_DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c); 131 | 132 | /** 133 | * @brief Draws filled rectangle on LCD 134 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 135 | * @param x: Top left X start point. Valid input is 0 to SSD1306_WIDTH - 1 136 | * @param y: Top left Y start point. Valid input is 0 to SSD1306_HEIGHT - 1 137 | * @param w: Rectangle width in units of pixels 138 | * @param h: Rectangle height in units of pixels 139 | * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 140 | * @retval None 141 | */ 142 | void SSD1306_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c); 143 | 144 | /** 145 | * @brief Draws triangle on LCD 146 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 147 | * @param x1: First coordinate X location. Valid input is 0 to SSD1306_WIDTH - 1 148 | * @param y1: First coordinate Y location. Valid input is 0 to SSD1306_HEIGHT - 1 149 | * @param x2: Second coordinate X location. Valid input is 0 to SSD1306_WIDTH - 1 150 | * @param y2: Second coordinate Y location. Valid input is 0 to SSD1306_HEIGHT - 1 151 | * @param x3: Third coordinate X location. Valid input is 0 to SSD1306_WIDTH - 1 152 | * @param y3: Third coordinate Y location. Valid input is 0 to SSD1306_HEIGHT - 1 153 | * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 154 | * @retval None 155 | */ 156 | void SSD1306_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color); 157 | 158 | /** 159 | * @brief Draws circle to STM buffer 160 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 161 | * @param x: X location for center of circle. Valid input is 0 to SSD1306_WIDTH - 1 162 | * @param y: Y location for center of circle. Valid input is 0 to SSD1306_HEIGHT - 1 163 | * @param r: Circle radius in units of pixels 164 | * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 165 | * @retval None 166 | */ 167 | void SSD1306_DrawCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c); 168 | 169 | /** 170 | * @brief Draws filled circle to STM buffer 171 | * @note @ref SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen 172 | * @param x: X location for center of circle. Valid input is 0 to SSD1306_WIDTH - 1 173 | * @param y: Y location for center of circle. Valid input is 0 to SSD1306_HEIGHT - 1 174 | * @param r: Circle radius in units of pixels 175 | * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration 176 | * @retval None 177 | */ 178 | void SSD1306_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c); 179 | 180 | void SSD1306_WRITECOMMAND(uint8_t command); 181 | 182 | #endif 183 | -------------------------------------------------------------------------------- /main/xi2c.c: -------------------------------------------------------------------------------- 1 | #include "xi2c.h" 2 | 3 | 4 | static esp_err_t XI2CWrite(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t* data_wr, size_t size); 5 | static esp_err_t XI2CRead(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t* data_rd, size_t size); 6 | 7 | static esp_err_t XI2CWrite(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t* data_wr, size_t size) { 8 | 9 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 10 | i2c_master_start(cmd); 11 | i2c_master_write_byte(cmd, ( i2c_add << 1 ), ACK_CHECK_DIS); 12 | i2c_master_write(cmd, data_wr, size, ACK_CHECK_DIS); 13 | i2c_master_stop(cmd); 14 | esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS); 15 | i2c_cmd_link_delete(cmd); 16 | return ret; 17 | } 18 | 19 | static esp_err_t XI2CRead(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t* data_rd, size_t size) { 20 | if (size == 0) { 21 | return ESP_OK; 22 | } 23 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 24 | i2c_master_start(cmd); 25 | i2c_master_write_byte(cmd, ( i2c_add << 1 ), ACK_CHECK_DIS); 26 | if (size > 1) { 27 | i2c_master_read(cmd, data_rd, size, ACK_VAL); 28 | } 29 | i2c_master_read_byte(cmd, data_rd + size, ACK_VAL); 30 | i2c_master_stop(cmd); 31 | esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS); 32 | i2c_cmd_link_delete(cmd); 33 | return ret; 34 | } 35 | 36 | esp_err_t X_WriteMulti(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint32_t count, uint8_t* data_wr) { 37 | if (count > sizeof(XI2CBuffer) - 1) { 38 | return ESP_FAIL; 39 | } 40 | XI2CBuffer[0] = index; 41 | memcpy(&XI2CBuffer[1], data_wr, count); 42 | esp_err_t ret = XI2CWrite(i2c_num, i2c_add, XI2CBuffer, count+1); 43 | return ret; 44 | } 45 | 46 | esp_err_t X_ReadMulti(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint32_t count, uint8_t* data_rd) { 47 | esp_err_t ret; 48 | 49 | ret = XI2CWrite(i2c_num, i2c_add, &index, 0x1); 50 | if (ret == ESP_FAIL) { 51 | return ret; 52 | } 53 | 54 | ret = XI2CRead(i2c_num, i2c_add, data_rd, count); 55 | return ret; 56 | } 57 | 58 | esp_err_t X_WrByte(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t data_wr) { 59 | 60 | XI2CBuffer[0] = index; 61 | XI2CBuffer[1] = data_wr; 62 | esp_err_t ret = XI2CWrite(i2c_num, i2c_add, XI2CBuffer, 0x2); 63 | return ret; 64 | 65 | } 66 | 67 | esp_err_t X_RdByte(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t *data_rd) { 68 | 69 | esp_err_t ret; 70 | 71 | ret = XI2CWrite(i2c_num, i2c_add, &index, 0x1); 72 | if (ret == ESP_FAIL) { 73 | return ret; 74 | } 75 | 76 | ret = XI2CRead(i2c_num, i2c_add, data_rd, 0x1); 77 | return ret; 78 | } 79 | 80 | esp_err_t X_WrBit(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t bitNum, uint8_t data_wr) { 81 | 82 | uint8_t b; 83 | esp_err_t ret; 84 | ret = X_RdByte(i2c_num, i2c_add, index, &b); 85 | if (ret == ESP_FAIL) { 86 | return ret; 87 | } 88 | b = (data_wr != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); 89 | ret = X_WrByte(i2c_num, i2c_add, index, b); 90 | return ret; 91 | 92 | } 93 | 94 | esp_err_t X_WrBits(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t bitStart, uint8_t length, uint8_t data_wr) { 95 | 96 | uint8_t b; 97 | // 010 value to write 98 | // 76543210 bit numbers 99 | // args: bitStart=4, length=3 100 | // 00011100 mask byte 101 | // 10101111 original value (sample) 102 | // 10100011 original & ~mask 103 | // 10101011 masked | value 104 | esp_err_t ret; 105 | ret = X_RdByte(i2c_num, i2c_add, index, &b); 106 | if (ret == ESP_FAIL) { 107 | return ret; 108 | } 109 | uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); 110 | data_wr <<= (bitStart - length + 1); // shift data into correct position 111 | data_wr &= mask; // zero all non-important bits in data 112 | b &= ~(mask); // zero all important bits in existing byte 113 | b |= data_wr; // combine data with existing byte 114 | ret = X_WrByte(i2c_num, i2c_add, index, b); 115 | return ret; 116 | 117 | } 118 | 119 | esp_err_t X_WrWord(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t data_wr) { 120 | 121 | XI2CBuffer[0] = index; 122 | XI2CBuffer[1] = data_wr >> 8; 123 | XI2CBuffer[2] = data_wr & 0x00FF; 124 | esp_err_t ret = XI2CWrite(i2c_num, i2c_add, XI2CBuffer, 0x3); 125 | return ret; 126 | 127 | } 128 | 129 | esp_err_t X_WrDWord(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t data_wr) { 130 | 131 | XI2CBuffer[0] = index; 132 | XI2CBuffer[1] = (data_wr >> 24) & 0xFF; 133 | XI2CBuffer[2] = (data_wr >> 16) & 0xFF; 134 | XI2CBuffer[3] = (data_wr >> 8) & 0xFF; 135 | XI2CBuffer[4] = (data_wr >> 0 ) & 0xFF; 136 | esp_err_t ret = XI2CWrite(i2c_num, i2c_add, XI2CBuffer, 0x5); 137 | return ret; 138 | 139 | } 140 | 141 | /*X_Error X_UpdateByte(SensorsData Dev, uint8_t index, uint8_t AndData, uint8_t OrData) { 142 | X_Error Status = X_ERROR_NONE; 143 | uint8_t data; 144 | 145 | Status = X_RdByte(Dev, index, &data); 146 | if (Status == 0) { 147 | goto done; 148 | } 149 | data = (data & AndData) | OrData; 150 | Status = X_WrByte(Dev, index, data); 151 | done: 152 | return Status; 153 | }*/ 154 | 155 | esp_err_t X_RdBit(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t bitNum, uint8_t *data_rd) { 156 | 157 | uint8_t b; 158 | esp_err_t ret; 159 | ret = X_RdByte(i2c_num, i2c_add, index, &b); 160 | if (ret == ESP_FAIL) { 161 | return ret; 162 | } 163 | *data_rd = b & (1 << bitNum); 164 | return ret; 165 | 166 | } 167 | 168 | esp_err_t X_RdBits(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t bitStart, uint8_t length, uint8_t *data_rd) { 169 | 170 | uint8_t b; 171 | esp_err_t ret; 172 | ret = X_RdByte(i2c_num, i2c_add, index, &b); 173 | if (ret == ESP_FAIL) { 174 | return ret; 175 | } 176 | uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); 177 | b &= mask; 178 | b >>= (bitStart - length + 1); 179 | *data_rd = b; 180 | return ret; 181 | 182 | } 183 | 184 | esp_err_t X_RdWord(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint16_t *data_rd) { 185 | 186 | esp_err_t ret; 187 | 188 | ret = XI2CWrite(i2c_num, i2c_add, &index, 0x1); 189 | if (ret == ESP_FAIL) { 190 | return ret; 191 | } 192 | 193 | ret = XI2CRead(i2c_num, i2c_add, XI2CBuffer, 0x2); 194 | 195 | *data_rd = ((uint16_t)XI2CBuffer[0]<<8) + (uint16_t)XI2CBuffer[1]; 196 | return ret; 197 | 198 | } 199 | 200 | esp_err_t X_RdDWord(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint32_t *data_rd) { 201 | 202 | esp_err_t ret; 203 | 204 | ret = XI2CWrite(i2c_num, i2c_add, &index, 0x1); 205 | if (ret == ESP_FAIL) { 206 | return ret; 207 | } 208 | 209 | ret = XI2CRead(i2c_num, i2c_add, XI2CBuffer, 0x4); 210 | 211 | *data_rd = ((uint32_t)XI2CBuffer[0]<<24) + ((uint32_t)XI2CBuffer[1]<<16) + ((uint32_t)XI2CBuffer[2]<<8) + (uint32_t)XI2CBuffer[3]; 212 | return ret; 213 | 214 | } 215 | 216 | esp_err_t X_PollingDelay(void) { 217 | 218 | esp_err_t ret; 219 | X_OsDelay(); 220 | ret = ESP_OK; 221 | return ret; 222 | 223 | } 224 | -------------------------------------------------------------------------------- /main/xi2c.h: -------------------------------------------------------------------------------- 1 | #ifndef I2C_H_ 2 | #define I2C_H_ 3 | 4 | #include "driver/i2c.h" 5 | #include "stdio.h" 6 | #include "string.h" 7 | #include "esp_system.h" 8 | #include 9 | #include "freertos/FreeRTOS.h" 10 | #include "freertos/task.h" 11 | 12 | #define X_OsDelay(...) vTaskDelay(20) 13 | 14 | #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ 15 | #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ 16 | #define ACK_VAL 0x0 /*!< I2C ack value */ 17 | #define NACK_VAL 0x1 /*!< I2C nack value */ 18 | 19 | uint8_t XI2CBuffer[512]; 20 | 21 | esp_err_t X_WriteMulti(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint32_t count, uint8_t* data_wr); 22 | esp_err_t X_ReadMulti(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint32_t count, uint8_t* data_rd); 23 | esp_err_t X_WrByte(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t data_wr); 24 | esp_err_t X_RdByte(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t *data_rd); 25 | esp_err_t X_WrBit(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t bitNum, uint8_t data_wr); 26 | esp_err_t X_WrBits(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t bitStart, uint8_t length, uint8_t data_wr); 27 | esp_err_t X_WrWord(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t data_wr); 28 | esp_err_t X_WrDWord(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t data_wr); 29 | esp_err_t X_RdBit(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t bitNum, uint8_t *data_rd); 30 | esp_err_t X_RdBits(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint8_t bitStart, uint8_t length, uint8_t *data_rd); 31 | esp_err_t X_RdWord(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint16_t *data_rd); 32 | esp_err_t X_RdDWord(i2c_port_t i2c_num, uint8_t i2c_add, uint8_t index, uint32_t *data_rd); 33 | esp_err_t X_PollingDelay(void); 34 | 35 | #endif /* I2C_H_ */ 36 | --------------------------------------------------------------------------------