├── .github └── workflows │ └── main.yml ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── EWSTM8 ├── vc288.ewp └── vc288.eww ├── README.md ├── platformio.ini └── src ├── adc.c ├── adc.h ├── clock.c ├── clock.h ├── config.h ├── config_8s003.h ├── display_7seg.c ├── display_7seg.h ├── eeprom.c ├── eeprom.h ├── gpio.h ├── gpio_8s003.c ├── main.c ├── stm8.h ├── stm8s_conf.h ├── timer.c └── timer.h /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: PlatformIO CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Cache pip 17 | uses: actions/cache@v2 18 | with: 19 | path: ~/.cache/pip 20 | key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 21 | restore-keys: | 22 | ${{ runner.os }}-pip- 23 | - name: Cache PlatformIO 24 | uses: actions/cache@v2 25 | with: 26 | path: ~/.platformio 27 | key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} 28 | - name: Set up Python 29 | uses: actions/setup-python@v2 30 | - name: Install PlatformIO 31 | run: | 32 | python -m pip install --upgrade pip 33 | pip install --upgrade platformio 34 | - name: Run PlatformIO 35 | run: pio run 36 | - uses: actions/upload-artifact@v2 37 | with: 38 | name: debug_firmware.hex 39 | path: .pio/build/stm8sblue_debug/firmware.hex 40 | if-no-files-found: error 41 | - uses: actions/upload-artifact@v2 42 | with: 43 | name: debug_firmware.elf 44 | path: .pio/build/stm8sblue_debug/firmware.elf 45 | if-no-files-found: error 46 | - uses: actions/upload-artifact@v2 47 | with: 48 | name: release_firmware.hex 49 | path: .pio/build/stm8sblue_release/firmware.hex 50 | if-no-files-found: error 51 | - uses: actions/upload-artifact@v2 52 | with: 53 | name: release_firmware.elf 54 | path: .pio/build/stm8sblue_release/firmware.elf 55 | if-no-files-found: error 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "platformio.platformio-ide" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "stm8s.h": "c", 4 | "config.h": "c", 5 | "timer.h": "c", 6 | "stm8.h": "c", 7 | "display_7seg.h": "c", 8 | "config_8s003.h": "c" 9 | } 10 | } -------------------------------------------------------------------------------- /EWSTM8/vc288.ewp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3 4 | 5 | Debug 6 | 7 | STM8 8 | 9 | 1 10 | 11 | General 12 | 4 13 | 14 | 2 15 | 1 16 | 1 17 | 21 | 26 | 31 | 35 | 39 | 43 | 47 | 52 | 57 | 61 | 65 | 70 | 74 | 79 | 83 | 87 | 91 | 95 | 99 | 103 | 108 | 113 | 118 | 122 | 123 | 124 | 125 | ICCSTM8 126 | 3 127 | 128 | 9 129 | 1 130 | 1 131 | 135 | 139 | 143 | 147 | 151 | 156 | 160 | 165 | 169 | 173 | 177 | 181 | 185 | 189 | 194 | 198 | 202 | 206 | 210 | 214 | 218 | 222 | 226 | 230 | 234 | 238 | 242 | 246 | 250 | 254 | 258 | 262 | 266 | 270 | 275 | 280 | 284 | 288 | 292 | 296 | 300 | 304 | 309 | 313 | 317 | 321 | 325 | 326 | 327 | 328 | ASTM8 329 | 3 330 | 331 | 2 332 | 1 333 | 1 334 | 338 | 342 | 346 | 350 | 355 | 359 | 363 | 367 | 371 | 375 | 379 | 383 | 387 | 391 | 395 | 399 | 403 | 407 | 411 | 415 | 419 | 423 | 427 | 431 | 435 | 439 | 443 | 447 | 451 | 455 | 459 | 463 | 467 | 471 | 472 | 473 | 474 | OBJCOPY 475 | 0 476 | 477 | 0 478 | 1 479 | 1 480 | 485 | 489 | 493 | 497 | 501 | 502 | 503 | 504 | CUSTOM 505 | 3 506 | 507 | 508 | 509 | 0 510 | 511 | 512 | 513 | BICOMP 514 | 0 515 | 516 | 517 | 518 | BUILDACTION 519 | 1 520 | 521 | 522 | 523 | 524 | 525 | 526 | ILINK 527 | 4 528 | 529 | 3 530 | 1 531 | 1 532 | 536 | 540 | 544 | 548 | 552 | 556 | 560 | 564 | 568 | 572 | 576 | 580 | 584 | 588 | 592 | 596 | 600 | 604 | 608 | 612 | 616 | 620 | 624 | 628 | 632 | 636 | 640 | 644 | 648 | 652 | 656 | 660 | 664 | 668 | 672 | 676 | 680 | 684 | 688 | 692 | 697 | 701 | 705 | 710 | 715 | 719 | 723 | 727 | 731 | 735 | 739 | 743 | 747 | 751 | 755 | 760 | 765 | 769 | 773 | 777 | 778 | 779 | 780 | IARCHIVE 781 | 3 782 | 783 | 0 784 | 1 785 | 1 786 | 790 | 794 | 798 | 799 | 800 | 801 | BILINK 802 | 0 803 | 804 | 805 | 806 | 807 | Release 808 | 809 | STM8 810 | 811 | 0 812 | 813 | General 814 | 4 815 | 816 | 2 817 | 1 818 | 0 819 | 823 | 828 | 833 | 837 | 841 | 845 | 849 | 854 | 859 | 863 | 867 | 872 | 876 | 881 | 885 | 889 | 893 | 897 | 901 | 905 | 910 | 915 | 920 | 924 | 925 | 926 | 927 | ICCSTM8 928 | 3 929 | 930 | 9 931 | 1 932 | 0 933 | 937 | 941 | 945 | 949 | 953 | 958 | 962 | 967 | 971 | 975 | 979 | 983 | 987 | 991 | 996 | 1000 | 1004 | 1008 | 1012 | 1016 | 1020 | 1024 | 1028 | 1032 | 1036 | 1040 | 1044 | 1048 | 1052 | 1056 | 1060 | 1064 | 1068 | 1072 | 1077 | 1082 | 1086 | 1090 | 1094 | 1098 | 1102 | 1106 | 1111 | 1115 | 1119 | 1123 | 1127 | 1128 | 1129 | 1130 | ASTM8 1131 | 3 1132 | 1133 | 2 1134 | 1 1135 | 0 1136 | 1140 | 1144 | 1148 | 1152 | 1157 | 1161 | 1165 | 1169 | 1173 | 1177 | 1181 | 1185 | 1189 | 1193 | 1197 | 1201 | 1205 | 1209 | 1213 | 1217 | 1221 | 1225 | 1229 | 1233 | 1237 | 1241 | 1245 | 1249 | 1253 | 1257 | 1261 | 1265 | 1269 | 1273 | 1274 | 1275 | 1276 | OBJCOPY 1277 | 0 1278 | 1279 | 0 1280 | 1 1281 | 0 1282 | 1287 | 1291 | 1295 | 1299 | 1303 | 1304 | 1305 | 1306 | CUSTOM 1307 | 3 1308 | 1309 | 1310 | 1311 | 0 1312 | 1313 | 1314 | 1315 | BICOMP 1316 | 0 1317 | 1318 | 1319 | 1320 | BUILDACTION 1321 | 1 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | ILINK 1329 | 4 1330 | 1331 | 3 1332 | 1 1333 | 0 1334 | 1338 | 1342 | 1346 | 1350 | 1354 | 1358 | 1362 | 1366 | 1370 | 1374 | 1378 | 1382 | 1386 | 1390 | 1394 | 1398 | 1402 | 1406 | 1410 | 1414 | 1418 | 1422 | 1426 | 1430 | 1434 | 1438 | 1442 | 1446 | 1450 | 1454 | 1458 | 1462 | 1466 | 1470 | 1474 | 1478 | 1482 | 1486 | 1490 | 1494 | 1499 | 1503 | 1507 | 1512 | 1517 | 1521 | 1525 | 1529 | 1533 | 1537 | 1541 | 1545 | 1549 | 1553 | 1557 | 1562 | 1567 | 1571 | 1575 | 1579 | 1580 | 1581 | 1582 | IARCHIVE 1583 | 3 1584 | 1585 | 0 1586 | 1 1587 | 0 1588 | 1592 | 1596 | 1600 | 1601 | 1602 | 1603 | BILINK 1604 | 0 1605 | 1606 | 1607 | 1608 | 1609 | src 1610 | 1611 | $PROJ_DIR$\..\src\adc.c 1612 | 1613 | 1614 | $PROJ_DIR$\..\src\adc.h 1615 | 1616 | 1617 | $PROJ_DIR$\..\src\clock.c 1618 | 1619 | 1620 | $PROJ_DIR$\..\src\clock.h 1621 | 1622 | 1623 | $PROJ_DIR$\..\src\config.h 1624 | 1625 | 1626 | $PROJ_DIR$\..\src\config_8s003.h 1627 | 1628 | 1629 | $PROJ_DIR$\..\src\display_7seg.c 1630 | 1631 | 1632 | $PROJ_DIR$\..\src\display_7seg.h 1633 | 1634 | 1635 | $PROJ_DIR$\..\src\eeprom.c 1636 | 1637 | 1638 | $PROJ_DIR$\..\src\eeprom.h 1639 | 1640 | 1641 | $PROJ_DIR$\..\src\gpio.h 1642 | 1643 | 1644 | $PROJ_DIR$\..\src\gpio_8s003.c 1645 | 1646 | 1647 | $PROJ_DIR$\..\src\main.c 1648 | 1649 | 1650 | $PROJ_DIR$\..\src\stm8.h 1651 | 1652 | 1653 | $PROJ_DIR$\..\src\stm8s_conf.h 1654 | 1655 | 1656 | $PROJ_DIR$\..\src\timer.c 1657 | 1658 | 1659 | $PROJ_DIR$\..\src\timer.h 1660 | 1661 | 1662 | 1663 | -------------------------------------------------------------------------------- /EWSTM8/vc288.eww: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $WS_DIR$\vc288.ewp 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vc288-alt-fw 2 | VC288 Volt-amp meter alternative firmware. Targets the cheap DSN-VC288 volt-amp meter that uses the STM8S003F MCU. 3 | 4 | # How to compile 5 | 1. [Install](https://code.visualstudio.com/download) Visual Studio Code in your system. 6 | 2. Install the [PlatformIO](https://platformio.org/install/ide?install=vscode) extension on Visual Studio Code. 7 | 3. Once these are installed, open the PlatformIO Home from the extension icon, and install the ST STM8 platform. 8 | 4. Open this repository, by either cloning it to a directory, or by unziping the zip archive. 9 | 5. Finally, build the code by navigating into the PlatformIO extension icon, and expanding the appropriate `release` build (for instance, `stm8sblue_release`). Select `Build` to build it; then `Upload` to upload the code to the chip using an STLinkV2. 10 | 11 | For more info and other tools to upload it, please consult the PlatformIO info page for ST STM8. 12 | 13 | # Load the pre-built files 14 | Since this project uses PlatformIO, a simple action can be added later to generate the .elf or .hex file for each pull request (or release) created for the ease of flashing a pre-compiled version. 15 | 16 | # Status 17 | This is still not fully fledged as the original. 18 | 19 | # TODOs: 20 | * Linearize the ADC readings to get a precise value out of it. 21 | * Support the STM8S103F MCU (other variants of the same voltmeter). 22 | * ... other stuff that will come out eventually. 23 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env] 12 | platform = ststm8 13 | board = stm8sdisco 14 | framework = spl 15 | 16 | ; settings for the STM8S003, 8K flash, 1K ram 17 | board_build.mcu = stm8s003f3p6 18 | board_build.extra_flags = -DSTM8S003 19 | board_upload.maximum_size = 8192 20 | board_upload.maximum_ram_size = 1024 21 | 22 | [env:stm8sblue_debug] 23 | build_type = debug 24 | build_flags = --debug --out-fmt-elf 25 | build_unflags = -Og -ggdb2 -g2 26 | 27 | debug_tool = custom 28 | debug_server = 29 | $PLATFORMIO_CORE_DIR/packages/tool-openocd/bin/openocd 30 | -f interface/stlink-dap.cfg 31 | -f target/stm8s003.cfg 32 | -c "init" 33 | -c "reset halt" 34 | 35 | [env:stm8sblue_release] 36 | upload_protocol = stlinkv2 -------------------------------------------------------------------------------- /src/adc.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "adc.h" 3 | #include 4 | 5 | #define VAR_ADC_SCAN 6 | 7 | static volatile uint16_t adc_meas_cnt = 0; 8 | static volatile uint32_t adc_ch3_avg = 0; 9 | static volatile uint32_t adc_ch4_avg = 0; 10 | static volatile uint16_t adc_ch3 = 0; 11 | static volatile uint16_t adc_ch4 = 0; 12 | static volatile uint8_t adc_complete = 0; 13 | 14 | 15 | void wait_adc_newsets(void) 16 | { 17 | while(adc_complete == 0){ 18 | wfi(); 19 | } 20 | adc_complete = 0; 21 | } 22 | 23 | // 24 | // ADC1 EOC handler. 25 | // 26 | ISR(ADC1_EOC_IRQHandler, ITC_IRQ_ADC1) 27 | { 28 | uint16_t temp16; 29 | uint8_t templ; 30 | #if !defined(VAR_ADC_SCAN) 31 | templ = ADC_DRH; 32 | temp16 = ((uint16_t)templ)<<8 | ADC_DRL; 33 | // Reset the EOC flag, otherwise it will fire again straight away. 34 | CLRBIT(ADC_CSR, ADC_CSR_EOC); 35 | if((ADC_CSR & ADC_CSR_CH2)==0){ 36 | adc_ch3_avg += temp16; 37 | CLRBIT(ADC_CSR, ADC_CSR_CH0); // - 38 | CLRBIT(ADC_CSR, ADC_CSR_CH1); // |> ADC samples AIN4 only. 39 | SETBIT(ADC_CSR, ADC_CSR_CH2); // | 40 | SETBIT(ADC_CR1, ADC_CR1_ADON); 41 | } 42 | else{ 43 | adc_ch4_avg += temp16; 44 | SETBIT(ADC_CSR, ADC_CSR_CH0); // - 45 | SETBIT(ADC_CSR, ADC_CSR_CH1); // |> ADC samples AIN3 only. 46 | CLRBIT(ADC_CSR, ADC_CSR_CH2); // | 47 | if (adc_meas_cnt++ == (1 << ADC_AVERAGE_SAMPLES_BASE_2)) 48 | { 49 | adc_ch3 = adc_ch3_avg >> ADC_AVERAGE_SAMPLES_BASE_2; 50 | adc_ch4 = adc_ch4_avg >> ADC_AVERAGE_SAMPLES_BASE_2; 51 | 52 | adc_meas_cnt = 0; 53 | adc_ch3_avg = 0; 54 | adc_ch4_avg = 0; 55 | adc_complete =1; 56 | } 57 | } 58 | #else 59 | templ= ADC_DB3RH; 60 | temp16= ((uint16_t)templ << 8) | ADC_DB3RL; 61 | adc_ch3_avg += temp16; 62 | templ= ADC_DB4RH; 63 | temp16= ((uint16_t)templ << 8) | ADC_DB4RL; 64 | adc_ch4_avg += temp16; 65 | // Reset the EOC flag, otherwise it will fire again straight away. 66 | CLRBIT(ADC_CSR, ADC_CSR_EOC); 67 | 68 | if (adc_meas_cnt++ == (1 << ADC_AVERAGE_SAMPLES_BASE_2)) 69 | { 70 | adc_ch3 = adc_ch3_avg >> ADC_AVERAGE_SAMPLES_BASE_2; 71 | adc_ch4 = adc_ch4_avg >> ADC_AVERAGE_SAMPLES_BASE_2; 72 | 73 | adc_meas_cnt = 0; 74 | adc_ch3_avg = 0; 75 | adc_ch4_avg = 0; 76 | adc_complete =1; 77 | } 78 | 79 | #endif 80 | } 81 | 82 | // 83 | // Setup ADC 1 in a slow prescaler, scan mode on, and buffered data with 84 | // external trigger (TRG0 output from TIM1). 85 | // 86 | /* From http://blog.mark-stevens.co.uk/2012/09/single-scan-adc-on-the-stm8s/ */ 87 | void setup_adc(void) 88 | { 89 | // Enable the ADC clock 90 | SETBIT(CLK_PCKENR2, CLK_PCKENR2_ADC); 91 | 92 | #if !defined(VAR_ADC_SCAN) 93 | // Turn ADC on. A second set is required to start the conversion. 94 | //SETBIT(ADC_CR1, ADC_CR1_ADON); 95 | CLRBIT(ADC_CR1, ADC_CR1_ADON); 96 | 97 | SETBIT(ADC_CSR, ADC_CSR_CH0); // - 98 | SETBIT(ADC_CSR, ADC_CSR_CH1); // |> ADC samples AIN3 only. 99 | CLRBIT(ADC_CSR, ADC_CSR_CH2); // | 100 | CLRBIT(ADC_CSR, ADC_CSR_CH3); // | 101 | 102 | SETBIT(ADC_CSR, ADC_CSR_EOCIE); // Enable the interrupt after conversion completed. 103 | 104 | CLRBIT(ADC_CR1, ADC_CR1_SPSEL0); // - 105 | CLRBIT(ADC_CR1, ADC_CR1_SPSEL1); // |> Prescaler = fmaster/8. 106 | SETBIT(ADC_CR1, ADC_CR1_SPSEL2); // - 107 | //CLRBIT(ADC_CR1, ADC_CR1_CONT); // - 108 | 109 | 110 | CLRBIT(ADC_CR3, ADC_CR3_DBUF); ///< When DBUF is set, converted values are stored in the ADC_DBxRH and ADC_DBxRL registers instead of the ADC_DRH and ADC_DRL registers. 111 | CLRBIT(ADC_CR2, ADC_CR2_SCAN); // Scan mode enabled 112 | SETBIT(ADC_CR2, ADC_CR2_EXTTRIG); // Conversion on external event enabled. 113 | CLRBIT(ADC_CR2, ADC_CR2_EXTSEL0); // - TIM1 TRG0 event output. 114 | CLRBIT(ADC_CR2, ADC_CR2_EXTSEL1); // - 115 | SETBIT(ADC_CR2, ADC_CR2_ALIGN); // Data is right aligned. 116 | #else 117 | // Turn ADC on. A second set is required to start the conversion. 118 | //SETBIT(ADC_CR1, ADC_CR1_ADON); 119 | CLRBIT(ADC_CR1, ADC_CR1_ADON); 120 | 121 | CLRBIT(ADC_CSR, ADC_CSR_CH0); // - 122 | CLRBIT(ADC_CSR, ADC_CSR_CH1); // |> ADC samples AIN4 only. 123 | SETBIT(ADC_CSR, ADC_CSR_CH2); // | 124 | CLRBIT(ADC_CSR, ADC_CSR_CH3); // | 125 | 126 | SETBIT(ADC_CSR, ADC_CSR_EOCIE); // Enable the interrupt after conversion completed. 127 | 128 | CLRBIT(ADC_CR1, ADC_CR1_SPSEL0); // - 129 | CLRBIT(ADC_CR1, ADC_CR1_SPSEL1); // |> Prescaler = fmaster/8. 130 | SETBIT(ADC_CR1, ADC_CR1_SPSEL2); // - 131 | //CLRBIT(ADC_CR1, ADC_CR1_CONT); // - 132 | 133 | SETBIT(ADC_CR3, ADC_CR3_DBUF); ///< When DBUF is set, converted values are stored in the ADC_DBxRH and ADC_DBxRL registers instead of the ADC_DRH and ADC_DRL registers. 134 | SETBIT(ADC_CR2, ADC_CR2_SCAN); // Scan mode enabled 135 | SETBIT(ADC_CR2, ADC_CR2_EXTTRIG); // Conversion on external event enabled. 136 | CLRBIT(ADC_CR2, ADC_CR2_EXTSEL0); // - TIM1 TRG0 event output. 137 | CLRBIT(ADC_CR2, ADC_CR2_EXTSEL1); // - 138 | SETBIT(ADC_CR2, ADC_CR2_ALIGN); // Data is right aligned. 139 | #endif 140 | 141 | /*------------------TDR configuration ---------------------------*/ 142 | ADC_TDRH = 0x00; 143 | ADC_TDRL = (1<<4)|(1<<3); 144 | 145 | SETBIT(ADC_CR1, ADC_CR1_ADON); 146 | } 147 | 148 | uint16_t get_adc_amps(void) 149 | { 150 | return adc_ch3; 151 | } 152 | 153 | uint16_t get_adc_volts(void) 154 | { 155 | return adc_ch4; 156 | } -------------------------------------------------------------------------------- /src/adc.h: -------------------------------------------------------------------------------- 1 | #ifndef __ADC_H 2 | #define __ADC_H 3 | 4 | #include 5 | 6 | void wait_adc_newsets(void); 7 | void setup_adc(void); 8 | uint16_t get_adc_amps(void); 9 | uint16_t get_adc_volts(void); 10 | 11 | #endif /* __ADC_H */ -------------------------------------------------------------------------------- /src/clock.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "clock.h" 3 | #include 4 | 5 | 6 | static uint32_t f_CPU = DEFAULT_SYSTEM_CORE_CLOCK; 7 | static uint32_t f_master = DEFAULT_SYSTEM_CORE_CLOCK; 8 | 9 | // 10 | // Setup the system clock to run at the requested speed using the internal RC. 11 | // 12 | void setup_clock(stm8s_core_clocks speed) 13 | { 14 | CLK_ICKR = 0; // Reset the Internal Clock Register. 15 | SETBIT(CLK_ICKR, CLK_ICKR_HSIEN); // Enable the HSI. 16 | CLK_ECKR = 0; // Disable the external clock. 17 | while ((CLK_ICKR & CLK_ICKR_HSIRDY) == 0); // Wait for the HSI to be ready for use. 18 | 19 | CLK_CKDIVR = speed; // Set the clock at the selected speed. 20 | 21 | CLK_PCKENR1 = 0x00; // Disable all peripheral clocks. 22 | CLK_PCKENR2 = 0x00; // Ditto. 23 | 24 | CLK_CCOR = 0; // Turn off CCO. 25 | CLK_HSITRIMR = 0; // Turn off any HSIU trimming. 26 | CLK_SWIMCCR = 0; // Set SWIM to run at clock / 2. 27 | CLK_SWR = 0xe1; // Use HSI as the clock source. 28 | 29 | CLK_SWCR = 0; // Reset the clock switch control register. 30 | SETBIT(CLK_SWCR, CLK_SWCR_SWEN); // Enable switching. 31 | 32 | while ((CLK_SWCR & CLK_SWCR_SWBSY) != 0); // Pause while the clock switch is busy. 33 | 34 | /* CLK_CKDIVR[4:3] sets the HSI prescaler (1, 2, 4, 8) */ 35 | f_master = HSI_RC_CLOCK_SPEED >> ((speed & 0x18) >> 3); 36 | /* CLK_CKDIVR[2:0] sets the CPU prescaler (1, 2, ... , 128) */ 37 | f_CPU = f_master >> (speed & 0x07); 38 | } 39 | 40 | uint32_t clock_get_f_master(void) 41 | { 42 | return f_master; 43 | } 44 | 45 | uint32_t clock_get_f_cpu(void) 46 | { 47 | return f_CPU; 48 | } 49 | 50 | // 51 | // Delay loop 52 | // 53 | // Actual delay depends on clock settings 54 | // and compiler optimization settings. 55 | // 56 | void delay(uint32_t n) 57 | { 58 | while (n-- > 0); 59 | } -------------------------------------------------------------------------------- /src/clock.h: -------------------------------------------------------------------------------- 1 | #ifndef __CLOCK_H 2 | #define __CLOCK_H 3 | 4 | #include 5 | 6 | #define STM8S_HSI_DIV_1 0x00 7 | #define STM8S_HSI_DIV_2 0x08 8 | #define STM8S_HSI_DIV_4 0x10 9 | #define STM8S_HSI_DIV_8 0x18 10 | #define STM8S_CPU_DIV_1 0x00 11 | #define STM8S_CPU_DIV_2 0x01 12 | #define STM8S_CPU_DIV_4 0x02 13 | #define STM8S_CPU_DIV_8 0x03 14 | #define STM8S_CPU_DIV_16 0x04 15 | #define STM8S_CPU_DIV_32 0x05 16 | #define STM8S_CPU_DIV_64 0x06 17 | #define STM8S_CPU_DIV_128 0x07 18 | 19 | typedef enum 20 | { 21 | CORE_16MHz = STM8S_HSI_DIV_1 | STM8S_CPU_DIV_1, /* (HSI / 1) / 1 */ 22 | CORE_8MHz = STM8S_HSI_DIV_2 | STM8S_CPU_DIV_1, /* (HSI / 2) / 1 */ 23 | CORE_4MHz = STM8S_HSI_DIV_4 | STM8S_CPU_DIV_1, /* (HSI / 4) / 1 */ 24 | CORE_2MHz = STM8S_HSI_DIV_8 | STM8S_CPU_DIV_1, /* (HSI / 8) / 1 */ 25 | CORE_1MHz = STM8S_HSI_DIV_8 | STM8S_CPU_DIV_2, /* (HSI / 8) / 2 */ 26 | CORE_500kHz = STM8S_HSI_DIV_8 | STM8S_CPU_DIV_4, /* (HSI / 8) / 4 */ 27 | CORE_250kHz = STM8S_HSI_DIV_8 | STM8S_CPU_DIV_8, /* (HSI / 8) / 8 */ 28 | CORE_125kHz = STM8S_HSI_DIV_8 | STM8S_CPU_DIV_16, /* (HSI / 8) / 16 */ 29 | CORE_65k5Hz = STM8S_HSI_DIV_8 | STM8S_CPU_DIV_32, /* (HSI / 8) / 32 */ 30 | CORE_31k25Hz = STM8S_HSI_DIV_8 | STM8S_CPU_DIV_64, /* (HSI / 8) / 64 */ 31 | CORE_15k625Hz = STM8S_HSI_DIV_8 | STM8S_CPU_DIV_128, /* (HSI / 8) / 128 */ 32 | } stm8s_core_clocks; 33 | 34 | uint32_t clock_get_f_master(void); 35 | uint32_t clock_get_f_cpu(void); 36 | 37 | void setup_clock(stm8s_core_clocks speed); 38 | void delay(uint32_t n); 39 | 40 | #endif /* __CLOCK_H */ -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_H 2 | #define __CONFIG_H 3 | 4 | /** 5 | * Leaves the SWIM pin enabled for debug (since its shared with the 7seg mux.) 6 | * Define this symbol to debug the code. As a side effect, one segment will be 7 | * garbled with the SWIM data. 8 | */ 9 | //#define SWIM_DEBUG_ENABLED 10 | 11 | /** 12 | * Defines how many samples are going to be averaged. 13 | * Note: the resulting number of samples is 2^ADC_AVERAGE_SAMPLES_BASE_2 14 | */ 15 | #define ADC_AVERAGE_SAMPLES_BASE_2 5 16 | 17 | /** 18 | * Set to float or double, depending on compiler availability 19 | */ 20 | #define HIGH_RES_FLOAT float 21 | 22 | /** 23 | * Define VOLTS_DISPLAY_ALIGN_LEFT and/or AMPS_DISPLAY_ALIGN_LEFT if the value 24 | * should be always aligned to the left of the display. This causes the decimal 25 | * place separator (the dot) to move according to the measured value. 26 | */ 27 | //#define VOLTS_DISPLAY_ALIGN_LEFT 28 | //#define AMPS_DISPLAY_ALIGN_LEFT 29 | 30 | #ifdef STM8S003 31 | #include "config_8s003.h" 32 | #else 33 | #error "No suitable processor selected" 34 | #endif 35 | 36 | #endif /* __CONFIG_H */ -------------------------------------------------------------------------------- /src/config_8s003.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_8S003_H 2 | #define __CONFIG_8S003_H 3 | 4 | #include "stm8.h" 5 | 6 | #define EEPROM_START_PTR 0x4000 7 | 8 | #define HSI_RC_CLOCK_SPEED 16000000UL // 16MHz 9 | #define DEFAULT_SYSTEM_CORE_CLOCK 2000000UL // 2MHz 10 | 11 | #define ADC1_ISR ADC1_EOC_vector 12 | #define TIM2_ISR TIM2_OVR_UIF_vector 13 | 14 | #define SEVEN_SEG_COMMON_CATHODE 1 15 | #define SEVEN_SEG_COMMON_ANODE 2 16 | 17 | 18 | //#define BOARD_HW_V1 19 | //#define BOARD_HW_V2 20 | #define BOARD_HW_V3 21 | 22 | /** 23 | * PDF from UpcycleElectronics states a common anode display, but 24 | * mine is a common cathode. 25 | * Use either COMMON_CATHODE or COMMON_ANODE. 26 | */ 27 | #if defined(BOARD_HW_V2) || defined(BOARD_HW_V1) 28 | #define DISPLAY_TYPE SEVEN_SEG_COMMON_CATHODE 29 | #elif defined(BOARD_HW_V3) 30 | #define DISPLAY_TYPE SEVEN_SEG_COMMON_ANODE 31 | #else 32 | #error defined BOARD_HW_V? 33 | #endif 34 | 35 | #define ADC_SCALE (3.3 / 1024.0) 36 | 37 | /* Resistance value for the combined elements R3 and RV2 from the sch */ 38 | #if defined(BOARD_HW_V2) || defined(BOARD_HW_V1) 39 | #define AMPS_RV2 20000.0 40 | #define AMPS_R3 180000.0 41 | #elif defined(BOARD_HW_V3) 42 | #define AMPS_RV2 4700.0 43 | #define AMPS_R3 47000.0 44 | #else 45 | #error defined BOARD_HW_V? 46 | #endif 47 | #define AMPS_R3_RV2 (AMPS_R3+(AMPS_RV2/2)) 48 | 49 | /* Resistance value for R4 from the sch */ 50 | #if defined(BOARD_HW_V2) || defined(BOARD_HW_V1) 51 | #define AMPS_R4 8200.0 52 | #elif defined(BOARD_HW_V3) 53 | #define AMPS_R4 4200.0 54 | #else 55 | #error defined BOARD_HW_V? 56 | #endif 57 | 58 | /* Resistance value for the on-board shunt */ 59 | #if defined(BOARD_HW_V2) || defined(BOARD_HW_V1) 60 | #define AMPS_SHUNT 0.02 61 | #elif defined(BOARD_HW_V3) 62 | #define AMPS_SHUNT 1.6 63 | #else 64 | #error defined BOARD_HW_V? 65 | #endif 66 | /* Non-inverting OpAmp formula */ 67 | #define GAIN_FOR_AMPS (((1 + (AMPS_R3_RV2 / AMPS_R4)) / AMPS_SHUNT) * ADC_SCALE) 68 | 69 | /* Resistance value for the combined elements R2 and RV1 from the sch */ 70 | #if defined(BOARD_HW_V2) || defined(BOARD_HW_V1) 71 | #define VOLTS_RV1 20000.0 72 | #define VOLTS_R2 270000.0 73 | #elif defined(BOARD_HW_V3) 74 | #define VOLTS_RV1 4200.0 75 | #define VOLTS_R2 72000.0 76 | #else 77 | #error defined BOARD_HW_V? 78 | #endif 79 | #define VOLTS_R2_RV1 (VOLTS_R2+(VOLTS_RV1/2)) 80 | 81 | /* Resistance value for R1 from the sch */ 82 | #if defined(BOARD_HW_V2) || defined(BOARD_HW_V1) 83 | #define VOLTS_R1 8200.0 84 | #elif defined(BOARD_HW_V3) 85 | #define VOLTS_R1 2200.0 86 | #else 87 | #error defined BOARD_HW_V? 88 | #endif 89 | /* Voltage divider formula */ 90 | #define GAIN_FOR_VOLTAGE (((VOLTS_R1 + VOLTS_R2_RV1) / VOLTS_R1) * ADC_SCALE) 91 | 92 | 93 | 94 | #if defined(BOARD_HW_V1) 95 | 96 | #define STPROG_PORT PD 97 | #define STPROG_PIN PIN6 98 | 99 | #define MCD_A_PORT PD 100 | #define MCD_A_PIN PIN1 101 | 102 | #define MCD_B_PORT PA 103 | #define MCD_B_PIN PIN3 104 | 105 | #define MCD_C_PORT PC 106 | #define MCD_C_PIN PIN3 107 | 108 | #define MCD_D_PORT PC 109 | #define MCD_D_PIN PIN6 110 | 111 | #define MCD_E_PORT PC 112 | #define MCD_E_PIN PIN7 113 | 114 | #define MCD_F_PORT PC 115 | #define MCD_F_PIN PIN4 116 | 117 | #define MCD_G_PORT PA 118 | #define MCD_G_PIN PIN2 119 | 120 | #define MCD_DP_PORT PC 121 | #define MCD_DP_PIN PIN5 122 | 123 | #define MCD1_AD1_PORT PD 124 | #define MCD1_AD1_PIN PIN4 125 | 126 | #define MCD1_AD2_PORT PD 127 | #define MCD1_AD2_PIN PIN6 128 | 129 | #define MCD1_AD3_PORT PD 130 | #define MCD1_AD3_PIN PIN5 131 | 132 | #define MCD2_AD1_PORT PB 133 | #define MCD2_AD1_PIN PIN5 134 | 135 | #define MCD2_AD2_PORT PA 136 | #define MCD2_AD2_PIN PIN1 137 | 138 | #define MCD2_AD3_PORT PB 139 | #define MCD2_AD3_PIN PIN4 140 | 141 | #elif defined(BOARD_HW_V2) 142 | 143 | #define STPROG_PORT PD 144 | #define STPROG_PIN PIN6 145 | 146 | #define MCD_A_PORT PD 147 | #define MCD_A_PIN PIN1 148 | 149 | #define MCD_B_PORT PA 150 | #define MCD_B_PIN PIN3 151 | 152 | #define MCD_C_PORT PC 153 | #define MCD_C_PIN PIN3 154 | 155 | #define MCD_D_PORT PC 156 | #define MCD_D_PIN PIN6 157 | 158 | #define MCD_E_PORT PC 159 | #define MCD_E_PIN PIN7 160 | 161 | #define MCD_F_PORT PC 162 | #define MCD_F_PIN PIN4 163 | 164 | #define MCD_G_PORT PA 165 | #define MCD_G_PIN PIN2 166 | 167 | #define MCD_DP_PORT PC 168 | #define MCD_DP_PIN PIN5 169 | 170 | #define MCD1_AD1_PORT PD 171 | #define MCD1_AD1_PIN PIN4 172 | 173 | #define MCD1_AD2_PORT PD 174 | #define MCD1_AD2_PIN PIN6 175 | 176 | #define MCD1_AD3_PORT PD 177 | #define MCD1_AD3_PIN PIN5 178 | 179 | #define MCD2_AD1_PORT PB 180 | #define MCD2_AD1_PIN PIN5 181 | 182 | #define MCD2_AD2_PORT PB 183 | #define MCD2_AD2_PIN PIN4 184 | 185 | #define MCD2_AD3_PORT PA 186 | #define MCD2_AD3_PIN PIN1 187 | 188 | #elif defined(BOARD_HW_V3) 189 | 190 | #define STPROG_PORT PD 191 | #define STPROG_PIN PIN6 192 | 193 | #define MCD_A_PORT PD 194 | #define MCD_A_PIN PIN1 195 | 196 | #define MCD_B_PORT PB 197 | #define MCD_B_PIN PIN5 198 | 199 | #define MCD_C_PORT PC 200 | #define MCD_C_PIN PIN3 201 | 202 | #define MCD_D_PORT PC 203 | #define MCD_D_PIN PIN6 204 | 205 | #define MCD_E_PORT PC 206 | #define MCD_E_PIN PIN7 207 | 208 | #define MCD_F_PORT PC 209 | #define MCD_F_PIN PIN4 210 | 211 | #define MCD_G_PORT PB 212 | #define MCD_G_PIN PIN4 213 | 214 | #define MCD_DP_PORT PC 215 | #define MCD_DP_PIN PIN5 216 | 217 | #define MCD1_AD1_PORT PD 218 | #define MCD1_AD1_PIN PIN4 219 | 220 | #define MCD1_AD2_PORT PD 221 | #define MCD1_AD2_PIN PIN6 222 | 223 | #define MCD1_AD3_PORT PD 224 | #define MCD1_AD3_PIN PIN5 225 | 226 | #define MCD2_AD1_PORT PA 227 | #define MCD2_AD1_PIN PIN3 228 | 229 | #define MCD2_AD2_PORT PA 230 | #define MCD2_AD2_PIN PIN2 231 | 232 | #define MCD2_AD3_PORT PA 233 | #define MCD2_AD3_PIN PIN1 234 | 235 | #else 236 | #error Not defined BOARD_HW_V?(1,2,3)!!! 237 | #endif 238 | 239 | 240 | #endif /* __CONFIG_8S003_H */ -------------------------------------------------------------------------------- /src/display_7seg.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "gpio.h" 3 | #include "timer.h" 4 | #include "display_7seg.h" 5 | #include 6 | 7 | /* Private variables */ 8 | static const uint8_t seven_seg_lut[] = { 9 | /*0*/ SEG_MASK_F | SEG_MASK_E | SEG_MASK_D | SEG_MASK_C | SEG_MASK_B | SEG_MASK_A, 10 | /*1*/ SEG_MASK_C | SEG_MASK_B, 11 | /*2*/ SEG_MASK_D | SEG_MASK_E | SEG_MASK_G | SEG_MASK_B | SEG_MASK_A, 12 | /*3*/ SEG_MASK_G | SEG_MASK_D | SEG_MASK_C | SEG_MASK_B | SEG_MASK_A, 13 | /*4*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_C | SEG_MASK_B, 14 | /*5*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_D | SEG_MASK_C | SEG_MASK_A, 15 | /*6*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_E | SEG_MASK_D | SEG_MASK_C | SEG_MASK_A, 16 | /*7*/ SEG_MASK_C | SEG_MASK_B | SEG_MASK_A, 17 | /*8*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_E | SEG_MASK_D | SEG_MASK_C | SEG_MASK_B | SEG_MASK_A, 18 | /*9*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_D | SEG_MASK_C | SEG_MASK_B | SEG_MASK_A, 19 | /*a*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_E | SEG_MASK_C | SEG_MASK_B | SEG_MASK_A,//0x77, 20 | /*b*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_E | SEG_MASK_D | SEG_MASK_A,//0x1F 21 | /*c*/ SEG_MASK_F | SEG_MASK_E | SEG_MASK_D | SEG_MASK_A,//0x4E 22 | /*d*/ SEG_MASK_G | SEG_MASK_E | SEG_MASK_D | SEG_MASK_C | SEG_MASK_B,//0x3D 23 | /*E*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_E | SEG_MASK_D | SEG_MASK_A,//0x4F 24 | /*F*/ SEG_MASK_G | SEG_MASK_F | SEG_MASK_E | SEG_MASK_A,//0x47 25 | /*off*/ 0x00 26 | }; 27 | 28 | static volatile uint8_t display_data[6] = { 0 }; 29 | static volatile uint8_t display_pos = 0; 30 | 31 | // 32 | // Timer 2 Overflow handler. 33 | // 34 | ISR(TIM2_UPD_OVF_IRQHandler, ITC_IRQ_TIM2_OVF) 35 | { 36 | if (++display_pos == 7) 37 | { 38 | display_pos = 0; 39 | } 40 | 41 | select_digit(-1); /* off all digit */ 42 | set_segments(display_data[display_pos]); /* And set the data */ 43 | select_digit(display_pos); /* Select the digit */ 44 | 45 | // Reset the interrupt, otherwise it will fire again straight away. 46 | CLRBIT(TIM2_SR1, TIM_SR1_UIF); 47 | } 48 | 49 | void set_display_from_int(uint16_t number, 50 | uint8_t row, 51 | uint8_t decimal_dots, 52 | uint8_t digits) 53 | { 54 | // Note: 8th bit controls the decimal place dot 55 | display_data[row+2] = (digits & 1 ? seven_seg_lut[number % 10] : 0) | 56 | (decimal_dots & 1 ? SEG_MASK_DP : 0); 57 | number /= 10; 58 | decimal_dots >>= 1; 59 | display_data[row+1] = (digits & 1 ? seven_seg_lut[number % 10] : 0) | 60 | (decimal_dots & 1 ? SEG_MASK_DP : 0); 61 | number /= 10; 62 | decimal_dots >>= 1; 63 | display_data[row+0] = (digits & 1 ? seven_seg_lut[number % 10] : 0) | 64 | (decimal_dots & 1 ? SEG_MASK_DP : 0); 65 | } -------------------------------------------------------------------------------- /src/display_7seg.h: -------------------------------------------------------------------------------- 1 | #ifndef __7SEGDISPLAY_H 2 | #define __7SEGDISPLAY_H 3 | 4 | #include 5 | 6 | #define SEG_MASK_A 0x40 7 | #define SEG_MASK_B 0x20 8 | #define SEG_MASK_C 0x10 9 | #define SEG_MASK_D 0x08 10 | #define SEG_MASK_E 0x04 11 | #define SEG_MASK_F 0x02 12 | #define SEG_MASK_G 0x01 13 | #define SEG_MASK_DP 0x80 14 | 15 | 16 | #define SIMBOL_L (SEG_MASK_F | SEG_MASK_E | SEG_MASK_D | SEG_MASK_A) 17 | #define SIMBOL_OFF 0 18 | 19 | enum 20 | { 21 | SEVEN_SEG_DP_NONE = 0, 22 | SEVEN_SEG_DP_RIGHTMOST = 1, 23 | SEVEN_SEG_DP_MIDDLE = 2, 24 | SEVEN_SEG_DP_LEFTMOST = 4, 25 | 26 | SEVEN_SEG_DP_ALL = 7, 27 | }; 28 | 29 | enum 30 | { 31 | SEVEN_SEG_DIGITS_NONE = 0, 32 | SEVEN_SEG_DIGITS_RIGHTMOST = 1, 33 | SEVEN_SEG_DIGITS_MIDDLE = 2, 34 | SEVEN_SEG_DIGITS_LEFTMOST = 4, 35 | 36 | SEVEN_SEG_DIGITS_ALL = 7, 37 | }; 38 | 39 | enum 40 | { 41 | SEVEN_SEG_FIRST_ROW = 0, 42 | SEVEN_SEG_SECOND_ROW = 3, 43 | }; 44 | 45 | void set_display_from_int(uint16_t number, 46 | uint8_t row, 47 | uint8_t decimal_dots, 48 | uint8_t digits); 49 | 50 | #endif /* __7SEGDISPLAY_H */ -------------------------------------------------------------------------------- /src/eeprom.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "eeprom.h" 3 | #include 4 | #include 5 | 6 | typedef struct 7 | { 8 | eeprom_settings_t settings; 9 | uint16_t crc; 10 | } eeprom_contents_t; 11 | static eeprom_contents_t eeprom_contents; 12 | 13 | /* 14 | // 16 12 5 15 | // The CCITT CRC 16 polynomial is X + X + X + 1. 16 | // In binary, this is the bit pattern 1 0001 0000 0010 0001, and in hex it 17 | // is 0x11021. 18 | // A 17 bit register is simulated by testing the MSB before shifting 19 | // the data, which affords us the luxury of specifiy the polynomial as a 20 | // 16 bit value, 0x1021. 21 | // Due to the way in which we process the CRC, the bits of the polynomial 22 | // are stored in reverse order. This makes the polynomial 0x8408. 23 | */ 24 | /* From http://www.drdobbs.com/implementing-the-ccitt-cyclical-redundan/199904926 */ 25 | #define POLY 0x8408 26 | 27 | uint16_t crc16(char *data_p, uint16_t length) 28 | { 29 | uint8_t i; 30 | uint16_t data; 31 | uint16_t crc; 32 | 33 | crc = 0xffff; 34 | 35 | if (length == 0) 36 | return (~crc); 37 | 38 | do { 39 | for (i = 0, data = (unsigned int)0xff & *data_p++; 40 | i < 8; 41 | i++, data >>= 1) 42 | { 43 | if ((crc & 0x0001) ^ (data & 0x0001)) 44 | crc = (crc >> 1) ^ POLY; 45 | else 46 | crc >>= 1; 47 | } 48 | } while (--length); 49 | 50 | crc = ~crc; 51 | 52 | data = crc; 53 | crc = (crc << 8) | (data >> 8 & 0xFF); 54 | 55 | return (crc); 56 | } 57 | 58 | const eeprom_settings_t * eeprom_get_settings(void) 59 | { 60 | return &eeprom_contents.settings; 61 | } 62 | 63 | void eeprom_load_defaults(const eeprom_settings_t * defaults) 64 | { 65 | memcpy(&eeprom_contents.settings, /* Copy the defaults */ 66 | defaults, /* into the current settings */ 67 | sizeof(eeprom_settings_t)); 68 | } 69 | 70 | int8_t eeprom_load_settings(void) 71 | { 72 | uint16_t crc; 73 | char * data = (char*)EEPROM_START_PTR; 74 | 75 | /* Calculate the CRC of the data that should be loaded */ 76 | crc = crc16(data, 77 | sizeof(eeprom_settings_t)); 78 | 79 | /* Check if it matches the stored CRC value */ 80 | if (((eeprom_contents_t*)data)->crc != crc) 81 | { 82 | /* Data in EEPROM is not valid */ 83 | return -1; 84 | } 85 | 86 | /* CRC is valid, so copy the data into the current settings */ 87 | memcpy(&eeprom_contents.settings, 88 | data, 89 | sizeof(eeprom_settings_t)); 90 | 91 | return 0; 92 | } 93 | 94 | /* Code snippets from http://blog.mark-stevens.co.uk/2013/09/storing-data-eeprom-stm8s/ */ 95 | void eeprom_store_settings(void) 96 | { 97 | char * data = (char*)EEPROM_START_PTR; 98 | 99 | // 100 | // Check if the EEPROM is write-protected. If it is then unlock the EEPROM. 101 | // 102 | if ((FLASH_IAPSR & FLASH_IAPSR_DUL) == 0) 103 | { 104 | FLASH_DUKR = 0xae; 105 | FLASH_DUKR = 0x56; 106 | } 107 | 108 | /* Update the CRC */ 109 | eeprom_contents.crc = crc16((char*)&eeprom_contents.settings, 110 | sizeof(eeprom_settings_t)); 111 | 112 | memcpy(data, &eeprom_contents, sizeof(eeprom_contents_t)); 113 | 114 | // 115 | // Now write protect the EEPROM. 116 | // 117 | CLRBIT(FLASH_IAPSR, FLASH_IAPSR_DUL); 118 | } -------------------------------------------------------------------------------- /src/eeprom.h: -------------------------------------------------------------------------------- 1 | #ifndef __EEPROM_H 2 | #define __EEPROM_H 3 | 4 | #include "config.h" 5 | #include 6 | 7 | typedef struct 8 | { 9 | uint16_t offset; 10 | HIGH_RES_FLOAT scaling; 11 | } adc_calibration_values_t; 12 | 13 | typedef struct 14 | { 15 | adc_calibration_values_t adc_amps; 16 | adc_calibration_values_t adc_volts; 17 | } eeprom_settings_t; 18 | 19 | const eeprom_settings_t * eeprom_get_settings(void); 20 | 21 | int8_t eeprom_load_settings(void); 22 | 23 | void eeprom_load_defaults(const eeprom_settings_t * defaults); 24 | 25 | void eeprom_store_settings(void); 26 | 27 | #endif /* __EEPROM_H */ -------------------------------------------------------------------------------- /src/gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef __GPIO_H 2 | #define __GPIO_H 3 | 4 | #include 5 | 6 | void swim_set_as_gpio(void); 7 | void setup_gpios(void); 8 | 9 | void set_segments(uint8_t data); 10 | void select_digit(uint8_t digit); 11 | 12 | uint8_t read_programming_pin(void); 13 | void programming_pin_control(uint8_t is_input); 14 | 15 | #endif /* __GPIO_H */ -------------------------------------------------------------------------------- /src/gpio_8s003.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "gpio.h" 3 | #include "display_7seg.h" 4 | 5 | 6 | #if DISPLAY_TYPE == SEVEN_SEG_COMMON_ANODE 7 | #define SEGDATASETS(data,mask) ((data&mask) == 0) 8 | #define SEGROWSELECT(digit,row) (digit == row) 9 | #else 10 | #define SEGDATASETS(data,mask) ((data&mask) != 0) 11 | #define SEGROWSELECT(digit,row) (digit != row) 12 | #endif 13 | 14 | 15 | void swim_set_as_gpio(void) 16 | { 17 | #if !defined(SWIM_DEBUG_ENABLED) 18 | SETBIT(PORT(PD,DDR), PIN1); /* out */ 19 | SETBIT(PORT(PD,CR1), PIN1); /* push pull */ 20 | CLRBIT(PORT(PD,CR2), PIN1); /* speed 2MHz*/ 21 | //CFG_GCR = CFG_GCR_SWD;// disable SWIM interface 22 | #endif 23 | } 24 | 25 | 26 | void setup_gpios(void) 27 | { 28 | /** 29 | * Data Direction Register: 30 | * 0: Input 31 | * 1: Output 32 | * 33 | * Input Register: 34 | * each bit corresponds to the pins value. 35 | * 36 | * Output Register: 37 | * each bit corresponds to the pins value. 38 | * 39 | * Control Register 1: 40 | * 0: Floating Input \ in input 41 | * 1: Pull-up / mode 42 | * 0: Pseudo open drain \ in output 43 | * 1: Push-pull / mode 44 | * 45 | * Control Register 2: 46 | * 0: Ext. Int disabled \ in input 47 | * 1: Ext. int enabled / mode 48 | * 0: Out speed 2MHz \ in output 49 | * 1: Out speed 10MHz / mode 50 | */ 51 | 52 | /* A */ 53 | #if !defined(SWIM_DEBUG_ENABLED) 54 | /* Note: PD1 is also used for SWIM. You can't use the segment A while using SWIM */ 55 | SETBIT(PORT(MCD_A_PORT,DDR), MCD_A_PIN); /* out */ 56 | SETBIT(PORT(MCD_A_PORT,CR1), MCD_A_PIN); /* push pull */ 57 | CLRBIT(PORT(MCD_A_PORT,CR2), MCD_A_PIN); /* speed 2MHz*/ 58 | #endif 59 | 60 | /* B */ 61 | SETBIT(PORT(MCD_B_PORT,DDR), MCD_B_PIN); /* out */ 62 | SETBIT(PORT(MCD_B_PORT,CR1), MCD_B_PIN); /* push pull */ 63 | CLRBIT(PORT(MCD_B_PORT,CR2), MCD_B_PIN); /* speed 2MHz*/ 64 | 65 | /* C */ 66 | SETBIT(PORT(MCD_C_PORT,DDR), MCD_C_PIN); /* out */ 67 | SETBIT(PORT(MCD_C_PORT,CR1), MCD_C_PIN); /* push pull */ 68 | CLRBIT(PORT(MCD_C_PORT,CR2), MCD_C_PIN); /* speed 2MHz*/ 69 | 70 | /* D */ 71 | SETBIT(PORT(MCD_D_PORT,DDR), MCD_D_PIN); /* out */ 72 | SETBIT(PORT(MCD_D_PORT,CR1), MCD_D_PIN); /* push pull */ 73 | CLRBIT(PORT(MCD_D_PORT,CR2), MCD_D_PIN); /* speed 2MHz*/ 74 | 75 | /* E */ 76 | SETBIT(PORT(MCD_E_PORT,DDR), MCD_E_PIN); /* out */ 77 | SETBIT(PORT(MCD_E_PORT,CR1), MCD_E_PIN); /* push pull */ 78 | CLRBIT(PORT(MCD_E_PORT,CR2), MCD_E_PIN); /* speed 2MHz*/ 79 | 80 | /* F */ 81 | SETBIT(PORT(MCD_F_PORT,DDR), MCD_F_PIN); /* out */ 82 | SETBIT(PORT(MCD_F_PORT,CR1), MCD_F_PIN); /* push pull */ 83 | CLRBIT(PORT(MCD_F_PORT,CR2), MCD_F_PIN); /* speed 2MHz*/ 84 | 85 | /* G */ 86 | SETBIT(PORT(MCD_G_PORT,DDR), MCD_G_PIN); /* out */ 87 | SETBIT(PORT(MCD_G_PORT,CR1), MCD_G_PIN); /* push pull */ 88 | CLRBIT(PORT(MCD_G_PORT,CR2), MCD_G_PIN); /* speed 2MHz*/ 89 | 90 | /* Decimal point */ 91 | SETBIT(PORT(MCD_DP_PORT,DDR), MCD_DP_PIN); /* out */ 92 | SETBIT(PORT(MCD_DP_PORT,CR1), MCD_DP_PIN); /* push pull */ 93 | CLRBIT(PORT(MCD_DP_PORT,CR2), MCD_DP_PIN); /* speed 2MHz*/ 94 | 95 | /** 96 | * First row of LEDs (common anodes/cathodes) 97 | */ 98 | SETBIT(PORT(MCD1_AD1_PORT,DDR), MCD1_AD1_PIN); /* out */ 99 | SETBIT(PORT(MCD1_AD1_PORT,CR1), MCD1_AD1_PIN); /* push pull */ 100 | CLRBIT(PORT(MCD1_AD1_PORT,CR2), MCD1_AD1_PIN); /* speed 2MHz*/ 101 | 102 | SETBIT(PORT(MCD1_AD2_PORT,DDR), MCD1_AD2_PIN); /* out */ 103 | SETBIT(PORT(MCD1_AD2_PORT,CR1), MCD1_AD2_PIN); /* push pull */ 104 | CLRBIT(PORT(MCD1_AD2_PORT,CR2), MCD1_AD2_PIN); /* speed 2MHz*/ 105 | 106 | SETBIT(PORT(MCD1_AD3_PORT,DDR), MCD1_AD3_PIN); /* out */ 107 | SETBIT(PORT(MCD1_AD3_PORT,CR1), MCD1_AD3_PIN); /* push pull */ 108 | CLRBIT(PORT(MCD1_AD3_PORT,CR2), MCD1_AD3_PIN); /* speed 2MHz*/ 109 | 110 | 111 | /* PD6 needs to be controlled with programming_pin_control() */ 112 | 113 | /** 114 | * Second row of LEDs (common anodes/cathodes) 115 | */ 116 | SETBIT(PORT(MCD2_AD1_PORT,DDR), MCD2_AD1_PIN); /* out */ 117 | SETBIT(PORT(MCD2_AD1_PORT,CR1), MCD2_AD1_PIN); /* push pull */ 118 | CLRBIT(PORT(MCD2_AD1_PORT,CR2), MCD2_AD1_PIN); /* speed 2MHz*/ 119 | 120 | SETBIT(PORT(MCD2_AD2_PORT,DDR), MCD2_AD2_PIN); /* out */ 121 | SETBIT(PORT(MCD2_AD2_PORT,CR1), MCD2_AD2_PIN); /* push pull */ 122 | CLRBIT(PORT(MCD2_AD2_PORT,CR2), MCD2_AD2_PIN); /* speed 2MHz*/ 123 | 124 | SETBIT(PORT(MCD2_AD3_PORT,DDR), MCD2_AD3_PIN); /* out */ 125 | SETBIT(PORT(MCD2_AD3_PORT,CR1), MCD2_AD3_PIN); /* push pull */ 126 | CLRBIT(PORT(MCD2_AD3_PORT,CR2), MCD2_AD3_PIN); /* speed 2MHz*/ 127 | } 128 | 129 | uint8_t read_programming_pin(void) 130 | { 131 | return (PORT(STPROG_PORT,IDR) & STPROG_PIN); 132 | } 133 | 134 | void programming_pin_control(uint8_t is_input) 135 | { 136 | if (is_input == 1) 137 | { 138 | CLRBIT(PORT(STPROG_PORT,DDR), STPROG_PIN); /* PD6 = in */ 139 | SETBIT(PORT(STPROG_PORT,CR1), STPROG_PIN); /* Pull-up */ 140 | CLRBIT(PORT(STPROG_PORT,CR2), STPROG_PIN); /* No intrerrupt */ 141 | } 142 | else 143 | { 144 | SETBIT(PORT(STPROG_PORT,DDR), STPROG_PIN); /* PD6 = out */ 145 | SETBIT(PORT(STPROG_PORT,CR1), STPROG_PIN); /* push pull */ 146 | CLRBIT(PORT(STPROG_PORT,CR2), STPROG_PIN); /* speed 2MHz */ 147 | } 148 | } 149 | 150 | 151 | void set_segments(uint8_t data) 152 | { 153 | // G 154 | if (SEGDATASETS(data, SEG_MASK_G)) { SETBIT(PORT(MCD_G_PORT,ODR), MCD_G_PIN); } else { CLRBIT(PORT(MCD_G_PORT,ODR), MCD_G_PIN); } 155 | 156 | // F 157 | if (SEGDATASETS(data, SEG_MASK_F)) { SETBIT(PORT(MCD_F_PORT,ODR), MCD_F_PIN); } else { CLRBIT(PORT(MCD_F_PORT,ODR), MCD_F_PIN); } 158 | 159 | // E 160 | if (SEGDATASETS(data, SEG_MASK_E)) { SETBIT(PORT(MCD_E_PORT,ODR), MCD_E_PIN); } else { CLRBIT(PORT(MCD_E_PORT,ODR), MCD_E_PIN); } 161 | 162 | // D 163 | if (SEGDATASETS(data, SEG_MASK_D)) { SETBIT(PORT(MCD_D_PORT,ODR), MCD_D_PIN); } else { CLRBIT(PORT(MCD_D_PORT,ODR), MCD_D_PIN); } 164 | 165 | // C 166 | if (SEGDATASETS(data, SEG_MASK_C)) { SETBIT(PORT(MCD_C_PORT,ODR), MCD_C_PIN); } else { CLRBIT(PORT(MCD_C_PORT,ODR), MCD_C_PIN); } 167 | 168 | // B 169 | if (SEGDATASETS(data, SEG_MASK_B)) { SETBIT(PORT(MCD_B_PORT,ODR), MCD_B_PIN); } else { CLRBIT(PORT(MCD_B_PORT,ODR), MCD_B_PIN); } 170 | 171 | #if !defined(SWIM_DEBUG_ENABLED) 172 | // A (same pin of SWIM) 173 | if (SEGDATASETS(data, SEG_MASK_A)) { SETBIT(PORT(MCD_A_PORT,ODR), MCD_A_PIN); } else { CLRBIT(PORT(MCD_A_PORT,ODR), MCD_A_PIN); } 174 | #endif 175 | 176 | // Dp 177 | if (SEGDATASETS(data, SEG_MASK_DP)) { SETBIT(PORT(MCD_DP_PORT,ODR), MCD_DP_PIN); } else { CLRBIT(PORT(MCD_DP_PORT,ODR), MCD_DP_PIN); } 178 | } 179 | 180 | void select_digit(uint8_t digit) 181 | { 182 | if (SEGROWSELECT(digit, 0)) { SETBIT(PORT(MCD1_AD1_PORT,ODR), MCD1_AD1_PIN); } else { CLRBIT(PORT(MCD1_AD1_PORT,ODR), MCD1_AD1_PIN); } 183 | if (SEGROWSELECT(digit, 1)) { SETBIT(PORT(MCD1_AD2_PORT,ODR), MCD1_AD2_PIN); } else { CLRBIT(PORT(MCD1_AD2_PORT,ODR), MCD1_AD2_PIN); } 184 | if (SEGROWSELECT(digit, 2)) { SETBIT(PORT(MCD1_AD3_PORT,ODR), MCD1_AD3_PIN); } else { CLRBIT(PORT(MCD1_AD3_PORT,ODR), MCD1_AD3_PIN); } 185 | 186 | if (SEGROWSELECT(digit, 3)) { SETBIT(PORT(MCD2_AD1_PORT,ODR), MCD2_AD1_PIN); } else { CLRBIT(PORT(MCD2_AD1_PORT,ODR), MCD2_AD1_PIN); } 187 | if (SEGROWSELECT(digit, 4)) { SETBIT(PORT(MCD2_AD2_PORT,ODR), MCD2_AD2_PIN); } else { CLRBIT(PORT(MCD2_AD2_PORT,ODR), MCD2_AD2_PIN); } 188 | if (SEGROWSELECT(digit, 5)) { SETBIT(PORT(MCD2_AD3_PORT,ODR), MCD2_AD3_PIN); } else { CLRBIT(PORT(MCD2_AD3_PORT,ODR), MCD2_AD3_PIN); } 189 | } -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stm8.h" 4 | #include "config.h" 5 | #include "clock.h" 6 | #include "timer.h" 7 | #include "adc.h" 8 | #include "gpio.h" 9 | #include "display_7seg.h" 10 | #include "eeprom.h" 11 | 12 | /* required per SDCC Compiler User Guide */ 13 | ISR(ADC1_EOC_IRQHandler, ITC_IRQ_ADC1); 14 | ISR(TIM2_UPD_OVF_IRQHandler, ITC_IRQ_TIM2_OVF); 15 | 16 | enum display_set_align 17 | { 18 | DISPLAY_ALIGN_LEFT = 0, 19 | DISPLAY_ALIGN_RIGHT = 1, 20 | }; 21 | 22 | /** 23 | * Default settings to be applied when the EEPROM contains 24 | * invalid data. 25 | * Data is being pulled from the appropriate config file for 26 | * the selected target. 27 | */ 28 | static const eeprom_settings_t default_settings = 29 | { 30 | .adc_amps = 31 | { 32 | .scaling = GAIN_FOR_AMPS, 33 | .offset = 0, 34 | }, 35 | .adc_volts = 36 | { 37 | .scaling = GAIN_FOR_VOLTAGE, 38 | .offset = 0, 39 | }, 40 | }; 41 | 42 | static void do_calibration(void) 43 | { 44 | eeprom_settings_t new_settings; 45 | 46 | /* Use the default settings as a starting point */ 47 | new_settings = default_settings; 48 | 49 | /* This should enable the ADC interrupts */ 50 | __enable_interrupt(); 51 | 52 | /* Wait a moment so the ADC settles */ 53 | wait_adc_newsets(); 54 | //delay(100000); 55 | 56 | /** 57 | * Current ADC values should correspond to an absolute zero, 58 | * so store whatever its read as the offset. 59 | */ 60 | new_settings.adc_amps.offset = get_adc_amps(); 61 | new_settings.adc_volts.offset = get_adc_volts(); 62 | 63 | /* And finally store the data to the EEPROM */ 64 | eeprom_load_defaults(&new_settings); 65 | eeprom_store_settings(); 66 | 67 | /* Disable the interrupts, which should stop the ADC ints */ 68 | __disable_interrupt(); 69 | } 70 | 71 | #ifndef roundf 72 | // SDCC doesn't have this function by default, so we're ignoring it for now. 73 | #define roundf(x) x 74 | #endif 75 | 76 | static void set_display_from_double( 77 | HIGH_RES_FLOAT value, 78 | const uint8_t pos, 79 | const enum display_set_align align 80 | ) 81 | { 82 | if (align == DISPLAY_ALIGN_LEFT) 83 | { 84 | /* Clamp to zero */ 85 | if (value < 0.0) 86 | { 87 | set_display_from_int( 88 | 0, 89 | pos, 90 | SEVEN_SEG_DP_LEFTMOST, 91 | SEVEN_SEG_DIGITS_ALL 92 | ); 93 | } 94 | else if (value >= 100.0) 95 | { 96 | /* 100. - 999. */ 97 | value = roundf(value); 98 | set_display_from_int( 99 | (uint16_t)(value), 100 | pos, 101 | SEVEN_SEG_DP_RIGHTMOST, 102 | SEVEN_SEG_DIGITS_ALL 103 | ); 104 | } 105 | else if (value >= 10.0) 106 | { 107 | /* 10.0 - 99.9 */ 108 | value = roundf(value * 10.0); 109 | set_display_from_int( 110 | (uint16_t)(value), 111 | pos, 112 | SEVEN_SEG_DP_MIDDLE, 113 | SEVEN_SEG_DIGITS_ALL 114 | ); 115 | } 116 | else if (value >= 1.0) 117 | { 118 | /* 1.00 - 9.99 */ 119 | value = roundf(value * 100.0); 120 | set_display_from_int( 121 | (uint16_t)(value), 122 | pos, 123 | SEVEN_SEG_DP_LEFTMOST, 124 | SEVEN_SEG_DIGITS_ALL 125 | ); 126 | } 127 | else 128 | { 129 | /* .000 - .999 */ 130 | value = roundf(value * 1000.0); 131 | set_display_from_int( 132 | (uint16_t)(value), 133 | pos, 134 | SEVEN_SEG_DP_NONE, 135 | SEVEN_SEG_DIGITS_ALL 136 | ); 137 | } 138 | } 139 | else 140 | { 141 | /* Clamp to zero */ 142 | if (value < 0.0) 143 | { 144 | set_display_from_int( 145 | 0, 146 | pos, 147 | SEVEN_SEG_DP_LEFTMOST, 148 | SEVEN_SEG_DIGITS_ALL 149 | ); 150 | } 151 | else if (value >= 100.0) 152 | { 153 | /* 100. - 999. */ 154 | value = roundf(value); 155 | set_display_from_int( 156 | (uint16_t)(value), 157 | pos, 158 | SEVEN_SEG_DP_RIGHTMOST, 159 | SEVEN_SEG_DIGITS_ALL 160 | ); 161 | } 162 | else if (value >= 10.0) 163 | { 164 | /* 10.0 - 99.9 */ 165 | value = roundf(value * 10.0); 166 | set_display_from_int( 167 | (uint16_t)(value), 168 | pos, 169 | SEVEN_SEG_DP_MIDDLE, 170 | SEVEN_SEG_DIGITS_ALL 171 | ); 172 | } 173 | else 174 | { 175 | /* 0.0 - 9.9 */ 176 | value = roundf(value * 100.0); 177 | set_display_from_int( 178 | (uint16_t)(value), 179 | pos, 180 | SEVEN_SEG_DP_MIDDLE, 181 | SEVEN_SEG_DIGITS_MIDDLE | SEVEN_SEG_DIGITS_RIGHTMOST 182 | ); 183 | } 184 | } 185 | } 186 | 187 | static void do_measure(void) 188 | { 189 | HIGH_RES_FLOAT value; 190 | const eeprom_settings_t * settings; 191 | 192 | /* Read the ADC settings */ 193 | settings = eeprom_get_settings(); 194 | 195 | /* Raw value from ADC */ 196 | value = get_adc_volts(); 197 | /* Offset */ 198 | value -= settings->adc_volts.offset; 199 | if (value < 0) { value = 0; } 200 | /* Scale */ 201 | value *= settings->adc_volts.scaling; 202 | #ifdef VOLTS_DISPLAY_ALIGN_LEFT 203 | set_display_from_double(value, SEVEN_SEG_FIRST_ROW, DISPLAY_ALIGN_LEFT); 204 | #else 205 | set_display_from_double(value, SEVEN_SEG_FIRST_ROW, DISPLAY_ALIGN_RIGHT); 206 | #endif 207 | /* Raw value from ADC */ 208 | value = get_adc_amps(); 209 | /* Offset */ 210 | value -= settings->adc_amps.offset; 211 | if (value < 0) { value = 0; } 212 | /* Scale */ 213 | value *= settings->adc_amps.scaling; 214 | #ifdef VOLTS_DISPLAY_ALIGN_LEFT 215 | set_display_from_double(value, SEVEN_SEG_SECOND_ROW, DISPLAY_ALIGN_LEFT); 216 | #else 217 | set_display_from_double(value, SEVEN_SEG_SECOND_ROW, DISPLAY_ALIGN_RIGHT); 218 | #endif 219 | } 220 | 221 | void main() 222 | { 223 | __disable_interrupt(); 224 | 225 | /* Switch to 16MHz */ 226 | setup_clock(CORE_16MHz); 227 | 228 | /* Set the internal state of all segments to off by default */ 229 | set_segments(0); 230 | /* And no digit selected */ 231 | select_digit(0xff); 232 | 233 | /* Load a default calibration if the EEPROM's content is not valid */ 234 | if (eeprom_load_settings() != 0) 235 | { 236 | eeprom_load_defaults(&default_settings); 237 | eeprom_store_settings(); 238 | } 239 | 240 | /* At this stage the ADC is only needed for the calibration */ 241 | setup_adc(); 242 | setup_timer1(); // this is the trigger needed for ADC sampling 243 | 244 | /** 245 | * Check if the user wants to calibrate the device by checking the 246 | * programming input pin before running the main code. 247 | */ 248 | programming_pin_control(1); 249 | 250 | if (read_programming_pin() == 0) 251 | { 252 | /* wait until the user stops removes the jumper on the programming pin */ 253 | while(!read_programming_pin()); 254 | /* execute the calibration routine */ 255 | do_calibration(); 256 | /* Calibration done, continue */ 257 | } 258 | else{ 259 | #if !defined(SWIM_DEBUG_ENABLED) || defined(NDEBUG) 260 | //swim disable 261 | swim_set_as_gpio(); 262 | #endif 263 | } 264 | 265 | /* Set the outputs (except the programming input pin) */ 266 | setup_gpios(); 267 | 268 | /* Leave programming pin as output (normal operation) */ 269 | programming_pin_control(0); 270 | 271 | /* Timer2 can be enabled now, so the 7 seg display gets updated */ 272 | setup_timer2(); 273 | 274 | __enable_interrupt(); 275 | 276 | // 277 | // Main loop 278 | // 279 | while (1) 280 | { 281 | wait_adc_newsets(); 282 | do_measure(); 283 | } 284 | } -------------------------------------------------------------------------------- /src/stm8.h: -------------------------------------------------------------------------------- 1 | #ifndef _STH8_H 2 | #define _STH8_H 3 | 4 | /* Handy macros for GPIO */ 5 | #define CONCAT(a, b) a##_##b 6 | #define PORT(a, b) CONCAT(a , b) 7 | 8 | // These are (sometimes) optimized by sdcc to use the bset/bres assembly 9 | // instructions. 10 | #define CLRBIT(REG, VALUE) REG &= ~VALUE 11 | #define SETBIT(REG, VALUE) REG |= VALUE 12 | 13 | #define PIN0 (1 << 0) 14 | #define PIN1 (1 << 1) 15 | #define PIN2 (1 << 2) 16 | #define PIN3 (1 << 3) 17 | #define PIN4 (1 << 4) 18 | #define PIN5 (1 << 5) 19 | #define PIN6 (1 << 6) 20 | #define PIN7 (1 << 7) 21 | 22 | /* Register addresses */ 23 | #define CCR *(volatile unsigned char *)0x7F0A 24 | 25 | /* Clock */ 26 | #define CLK_ICKR *(volatile unsigned char *)0x50C0 27 | #define CLK_ECKR *(volatile unsigned char *)0x50C1 28 | #define CLK_CMSR *(volatile unsigned char *)0x50C3 29 | #define CLK_SWR *(volatile unsigned char *)0x50C4 30 | #define CLK_SWCR *(volatile unsigned char *)0x50C5 31 | #define CLK_CKDIVR *(volatile unsigned char *)0x50C6 32 | #define CLK_PCKENR1 *(volatile unsigned char *)0x50C7 33 | #define CLK_PCKENR2 *(volatile unsigned char *)0x50CA 34 | #define CLK_CSSR *(volatile unsigned char *)0x50C8 35 | #define CLK_CCOR *(volatile unsigned char *)0x50C9 36 | #define CLK_HSITRIMR *(volatile unsigned char *)0x50CC 37 | #define CLK_SWIMCCR *(volatile unsigned char *)0x50CD 38 | 39 | #define CLK_ICKR_REGAH (1 << 5) 40 | #define CLK_ICKR_LSIRDY (1 << 4) 41 | #define CLK_ICKR_LSIEN (1 << 3) 42 | #define CLK_ICKR_FHWU (1 << 2) 43 | #define CLK_ICKR_HSIRDY (1 << 1) 44 | #define CLK_ICKR_HSIEN (1 << 0) 45 | 46 | #define CLK_ECKR_HSERDY (1 << 1) 47 | #define CLK_ECKR_HSEEN (1 << 0) 48 | 49 | #define CLK_SWCR_SWIF (1 << 3) 50 | #define CLK_SWCR_SWIEN (1 << 2) 51 | #define CLK_SWCR_SWEN (1 << 1) 52 | #define CLK_SWCR_SWBSY (1 << 0) 53 | 54 | #define CLK_PCKENR1_TIM1 (1 << 7) 55 | #define CLK_PCKENR1_TIM3 (1 << 6) 56 | #define CLK_PCKENR1_TIM2 (1 << 5) 57 | #define CLK_PCKENR1_TIM5 (1 << 5) 58 | #define CLK_PCKENR1_TIM4 (1 << 4) 59 | #define CLK_PCKENR1_TIM6 (1 << 4) 60 | #define CLK_PCKENR1_CKEN13 (1 << 3) 61 | #define CLK_PCKENR1_CKEN12 (1 << 2) 62 | #define CLK_PCKENR1_SPI (1 << 1) 63 | #define CLK_PCKENR1_I2C (1 << 0) 64 | 65 | #define CLK_PCKENR2_CAN (1 << 7) 66 | #define CLK_PCKENR2_ADC (1 << 3) 67 | #define CLK_PCKENR2_AWU (1 << 2) 68 | 69 | #define CLK_CSSR_CSSD (1 << 3) 70 | #define CLK_CSSR_CSSDIE (1 << 2) 71 | #define CLK_CSSR_AUX (1 << 1) 72 | #define CLK_CSSR_CSSEN (1 << 0) 73 | 74 | #define CLK_CCOR_CCOBSY (1 << 6) 75 | #define CLK_CCOR_CCORDY (1 << 5) 76 | #define CLK_CCOR_CCOSEL3 (1 << 4) 77 | #define CLK_CCOR_CCOSEL2 (1 << 3) 78 | #define CLK_CCOR_CCOSEL1 (1 << 2) 79 | #define CLK_CCOR_CCOSEL0 (1 << 1) 80 | #define CLK_CCOR_CCOEN (1 << 0) 81 | 82 | #define CLK_SWIMCCR_SWIMCLK (1 << 0) 83 | 84 | /* GPIO */ 85 | #define PA_ODR *(volatile unsigned char *)0x5000 86 | #define PA_IDR *(volatile unsigned char *)0x5001 87 | #define PA_DDR *(volatile unsigned char *)0x5002 88 | #define PA_CR1 *(volatile unsigned char *)0x5003 89 | #define PA_CR2 *(volatile unsigned char *)0x5004 90 | 91 | #define PB_ODR *(volatile unsigned char *)0x5005 92 | #define PB_IDR *(volatile unsigned char *)0x5006 93 | #define PB_DDR *(volatile unsigned char *)0x5007 94 | #define PB_CR1 *(volatile unsigned char *)0x5008 95 | #define PB_CR2 *(volatile unsigned char *)0x5009 96 | 97 | #define PC_ODR *(volatile unsigned char *)0x500A 98 | #define PC_IDR *(volatile unsigned char *)0x500B 99 | #define PC_DDR *(volatile unsigned char *)0x500C 100 | #define PC_CR1 *(volatile unsigned char *)0x500D 101 | #define PC_CR2 *(volatile unsigned char *)0x500E 102 | 103 | #define PD_ODR *(volatile unsigned char *)0x500F 104 | #define PD_IDR *(volatile unsigned char *)0x5010 105 | #define PD_DDR *(volatile unsigned char *)0x5011 106 | #define PD_CR1 *(volatile unsigned char *)0x5012 107 | #define PD_CR2 *(volatile unsigned char *)0x5013 108 | 109 | #define EXTI_CR1 *(volatile unsigned char *)0x50A0 110 | #define EXTI_CR2 *(volatile unsigned char *)0x50A1 111 | 112 | /* Flash */ 113 | #define FLASH_CR1 *(volatile unsigned char*)0x505A 114 | #define FLASH_CR2 *(volatile unsigned char*)0x505B 115 | #define FLASH_NCR2 *(volatile unsigned char*)0x505C 116 | #define FLASH_FPR *(volatile unsigned char*)0x505D 117 | #define FLASH_NFPR *(volatile unsigned char*)0x505E 118 | #define FLASH_IAPSR *(volatile unsigned char*)0x505F 119 | #define FLASH_PUKR *(volatile unsigned char*)0x5062 120 | #define FLASH_DUKR *(volatile unsigned char*)0x5064 121 | 122 | #define FLASH_IAPSR_HVOFF (1 << 6) 123 | #define FLASH_IAPSR_DUL (1 << 3) 124 | 125 | /* UART */ 126 | #define UART1_SR *(volatile unsigned char *)0x5230 127 | #define UART1_DR *(volatile unsigned char *)0x5231 128 | #define UART1_BRR1 *(volatile unsigned char *)0x5232 129 | #define UART1_BRR2 *(volatile unsigned char *)0x5233 130 | #define UART1_CR1 *(volatile unsigned char *)0x5234 131 | #define UART1_CR2 *(volatile unsigned char *)0x5235 132 | #define UART1_CR3 *(volatile unsigned char *)0x5236 133 | #define UART1_CR4 *(volatile unsigned char *)0x5237 134 | #define UART1_CR5 *(volatile unsigned char *)0x5238 135 | #define UART1_GTR *(volatile unsigned char *)0x5239 136 | #define UART1_PSCR *(volatile unsigned char *)0x523A 137 | 138 | #define UART_SR_TXE (1 << 7) 139 | #define UART_SR_TC (1 << 6) 140 | #define UART_SR_RXNE (1 << 5) 141 | #define UART_SR_IDLE (1 << 4) 142 | #define UART_SR_OR (1 << 3) 143 | #define UART_SR_NF (1 << 2) 144 | #define UART_SR_FE (1 << 1) 145 | #define UART_SR_PE (1 << 0) 146 | 147 | #define UART_CR1_R8 (1 << 7) 148 | #define UART_CR1_T8 (1 << 6) 149 | #define UART_CR1_UARTD (1 << 5) 150 | #define UART_CR1_M (1 << 4) 151 | #define UART_CR1_WAKE (1 << 3) 152 | #define UART_CR1_PCEN (1 << 2) 153 | #define UART_CR1_PS (1 << 1) 154 | #define UART_CR1_PIEN (1 << 0) 155 | 156 | #define UART_CR2_TIEN (1 << 7) 157 | #define UART_CR2_TCIEN (1 << 6) 158 | #define UART_CR2_RIEN (1 << 5) 159 | #define UART_CR2_ILIEN (1 << 4) 160 | #define UART_CR2_TEN (1 << 3) 161 | #define UART_CR2_REN (1 << 2) 162 | #define UART_CR2_RWU (1 << 1) 163 | #define UART_CR2_SBK (1 << 0) 164 | 165 | #define UART_CR3_LINEN (1 << 6) 166 | #define UART_CR3_STOP2 (1 << 5) 167 | #define UART_CR3_STOP1 (1 << 4) 168 | #define UART_CR3_CLKEN (1 << 3) 169 | #define UART_CR3_CPOL (1 << 2) 170 | #define UART_CR3_CPHA (1 << 1) 171 | #define UART_CR3_LBCL (1 << 0) 172 | 173 | /* Timers */ 174 | #define TIM1_CR1 *(volatile unsigned char *)0x5250 175 | #define TIM1_CR2 *(volatile unsigned char *)0x5251 176 | #define TIM1_SMCR *(volatile unsigned char *)0x5252 177 | #define TIM1_ETR *(volatile unsigned char *)0x5253 178 | #define TIM1_IER *(volatile unsigned char *)0x5254 179 | #define TIM1_SR1 *(volatile unsigned char *)0x5255 180 | #define TIM1_SR2 *(volatile unsigned char *)0x5256 181 | #define TIM1_EGR *(volatile unsigned char *)0x5257 182 | #define TIM1_CCMR1 *(volatile unsigned char *)0x5258 183 | #define TIM1_CCMR2 *(volatile unsigned char *)0x5259 184 | #define TIM1_CCMR3 *(volatile unsigned char *)0x525A 185 | #define TIM1_CCMR4 *(volatile unsigned char *)0x525B 186 | #define TIM1_CCER1 *(volatile unsigned char *)0x525C 187 | #define TIM1_CCER2 *(volatile unsigned char *)0x525D 188 | #define TIM1_CNTRH *(volatile unsigned char *)0x525E 189 | #define TIM1_CNTRL *(volatile unsigned char *)0x525F 190 | #define TIM1_PSCRH *(volatile unsigned char *)0x5260 191 | #define TIM1_PSCRL *(volatile unsigned char *)0x5261 192 | #define TIM1_ARRH *(volatile unsigned char *)0x5262 193 | #define TIM1_ARRL *(volatile unsigned char *)0x5263 194 | #define TIM1_RCR *(volatile unsigned char *)0x5264 195 | #define TIM1_CCR1H *(volatile unsigned char *)0x5265 196 | #define TIM1_CCR1L *(volatile unsigned char *)0x5266 197 | #define TIM1_CCR2H *(volatile unsigned char *)0x5267 198 | #define TIM1_CCR2L *(volatile unsigned char *)0x5268 199 | #define TIM1_CCR3H *(volatile unsigned char *)0x5269 200 | #define TIM1_CCR3L *(volatile unsigned char *)0x526A 201 | #define TIM1_CCR4H *(volatile unsigned char *)0x526B 202 | #define TIM1_CCR4L *(volatile unsigned char *)0x526C 203 | #define TIM1_BKR *(volatile unsigned char *)0x526D 204 | #define TIM1_DTR *(volatile unsigned char *)0x526E 205 | #define TIM1_OISR *(volatile unsigned char *)0x526F 206 | 207 | /* Note these are for STM8S103 and STM8S003 208 | STM8S105,104/207/208 are different */ 209 | #define TIM2_CR1 *(volatile unsigned char *)0x5300 210 | #define TIM2_CR2 *(volatile unsigned char *)0x5301 211 | #define TIM2_SMCR *(volatile unsigned char *)0x5302 212 | #define TIM2_IER *(volatile unsigned char *)0x5303 213 | #define TIM2_SR1 *(volatile unsigned char *)0x5304 214 | #define TIM2_SR2 *(volatile unsigned char *)0x5305 215 | #define TIM2_EGR *(volatile unsigned char *)0x5306 216 | #define TIM2_CCMR1 *(volatile unsigned char *)0x5307 217 | #define TIM2_CCMR2 *(volatile unsigned char *)0x5308 218 | #define TIM2_CCMR3 *(volatile unsigned char *)0x5309 219 | #define TIM2_CCER1 *(volatile unsigned char *)0x530A 220 | #define TIM2_CCER2 *(volatile unsigned char *)0x530B 221 | #define TIM2_CNTRH *(volatile unsigned char *)0x530C 222 | #define TIM2_CNTRL *(volatile unsigned char *)0x530D 223 | #define TIM2_PSCR *(volatile unsigned char *)0x530E 224 | #define TIM2_ARRH *(volatile unsigned char *)0x530F 225 | #define TIM2_ARRL *(volatile unsigned char *)0x5310 226 | #define TIM2_CCR1H *(volatile unsigned char *)0x5311 227 | #define TIM2_CCR1L *(volatile unsigned char *)0x5312 228 | #define TIM2_CCR2H *(volatile unsigned char *)0x5313 229 | #define TIM2_CCR2L *(volatile unsigned char *)0x5314 230 | #define TIM2_CCR3H *(volatile unsigned char *)0x5315 231 | #define TIM2_CCR3L *(volatile unsigned char *)0x5316 232 | 233 | /* Note these are for STM8S103 and STM8S003 234 | STM8S105,104/207/208 are different */ 235 | #define TIM4_CR1 *(volatile unsigned char *)0x5340 236 | #define TIM4_CR2 *(volatile unsigned char *)0x5341 237 | #define TIM4_SMCR *(volatile unsigned char *)0x5342 238 | #define TIM4_IER *(volatile unsigned char *)0x5343 239 | #define TIM4_SR *(volatile unsigned char *)0x5344 240 | #define TIM4_EGR *(volatile unsigned char *)0x5345 241 | #define TIM4_CNTR *(volatile unsigned char *)0x5346 242 | #define TIM4_PSCR *(volatile unsigned char *)0x5347 243 | #define TIM4_ARR *(volatile unsigned char *)0x5348 244 | 245 | #define TIM_IER_BIE (1 << 7) 246 | #define TIM_IER_TIE (1 << 6) 247 | #define TIM_IER_COMIE (1 << 5) 248 | #define TIM_IER_CC4IE (1 << 4) 249 | #define TIM_IER_CC3IE (1 << 3) 250 | #define TIM_IER_CC2IE (1 << 2) 251 | #define TIM_IER_CC1IE (1 << 1) 252 | #define TIM_IER_UIE (1 << 0) 253 | 254 | #define TIM_CR1_APRE (1 << 7) 255 | #define TIM_CR1_CMSH (1 << 6) 256 | #define TIM_CR1_CMSL (1 << 5) 257 | #define TIM_CR1_DIR (1 << 4) 258 | #define TIM_CR1_OPM (1 << 3) 259 | #define TIM_CR1_URS (1 << 2) 260 | #define TIM_CR1_UDIS (1 << 1) 261 | #define TIM_CR1_CEN (1 << 0) 262 | 263 | #define TIM_CR2_MMS2 (1 << 6) 264 | #define TIM_CR2_MMS1 (1 << 5) 265 | #define TIM_CR2_MMS0 (1 << 4) 266 | 267 | #define TIM_IER_UIE (1 << 0) 268 | 269 | #define TIM_SR1_BIF (1 << 7) 270 | #define TIM_SR1_TIF (1 << 6) 271 | #define TIM_SR1_COMIF (1 << 5) 272 | #define TIM_SR1_CC4IF (1 << 4) 273 | #define TIM_SR1_CC3IF (1 << 3) 274 | #define TIM_SR1_CC2IF (1 << 2) 275 | #define TIM_SR1_CC1IF (1 << 1) 276 | #define TIM_SR1_UIF (1 << 0) 277 | 278 | /* SPI */ 279 | #define SPI_CR1 *(volatile unsigned char *)0x5200 280 | #define SPI_CR2 *(volatile unsigned char *)0x5201 281 | #define SPI_ICR *(volatile unsigned char *)0x5202 282 | #define SPI_SR *(volatile unsigned char *)0x5203 283 | #define SPI_DR *(volatile unsigned char *)0x5204 284 | #define SPI_CRCPR *(volatile unsigned char *)0x5205 285 | #define SPI_RXCRCR *(volatile unsigned char *)0x5206 286 | #define SPI_TXCRCR *(volatile unsigned char *)0x5207 287 | 288 | #define SPI_CR1_LSBFIRST (1 << 7) 289 | #define SPI_CR1_SPE (1 << 6) 290 | #define SPI_CR1_BR(br) ((br) << 3) 291 | #define SPI_CR1_MSTR (1 << 2) 292 | #define SPI_CR1_CPOL (1 << 1) 293 | #define SPI_CR1_CPHA (1 << 0) 294 | 295 | #define SPI_CR2_BDM (1 << 7) 296 | #define SPI_CR2_BDOE (1 << 6) 297 | #define SPI_CR2_CRCEN (1 << 5) 298 | #define SPI_CR2_CRCNEXT (1 << 4) 299 | #define SPI_CR2_RXONLY (1 << 2) 300 | #define SPI_CR2_SSM (1 << 1) 301 | #define SPI_CR2_SSI (1 << 0) 302 | 303 | #define SPI_ICR_TXIE (1 << 7) 304 | #define SPI_ICR_RXIE (1 << 6) 305 | #define SPI_ICR_ERRIE (1 << 5) 306 | #define SPI_ICR_WKIE (1 << 4) 307 | 308 | #define SPI_SR_BSY (1 << 7) 309 | #define SPI_SR_OVR (1 << 6) 310 | #define SPI_SR_MODF (1 << 5) 311 | #define SPI_SR_CRCERR (1 << 4) 312 | #define SPI_SR_WKUP (1 << 3) 313 | #define SPI_SR_TXE (1 << 1) 314 | #define SPI_SR_RxNE (1 << 0) 315 | 316 | /* I2C */ 317 | #define I2C_CR1 *(volatile unsigned char *)0x5210 318 | #define I2C_CR2 *(volatile unsigned char *)0x5211 319 | #define I2C_FREQR *(volatile unsigned char *)0x5212 320 | #define I2C_OARL *(volatile unsigned char *)0x5213 321 | #define I2C_OARH *(volatile unsigned char *)0x5214 322 | #define I2C_DR *(volatile unsigned char *)0x5216 323 | #define I2C_SR1 *(volatile unsigned char *)0x5217 324 | #define I2C_SR2 *(volatile unsigned char *)0x5218 325 | #define I2C_SR3 *(volatile unsigned char *)0x5219 326 | #define I2C_ITR *(volatile unsigned char *)0x521A 327 | #define I2C_CCRL *(volatile unsigned char *)0x521B 328 | #define I2C_CCRH *(volatile unsigned char *)0x521C 329 | #define I2C_TRISER *(volatile unsigned char *)0x521D 330 | #define I2C_PECR *(volatile unsigned char *)0x521E 331 | 332 | /* ADC */ 333 | #define ADC_DB0RH *(volatile unsigned char *)0x53E0 334 | #define ADC_DB0RL *(volatile unsigned char *)0x53E1 335 | #define ADC_DB1RH *(volatile unsigned char *)0x53E2 336 | #define ADC_DB1RL *(volatile unsigned char *)0x53E3 337 | #define ADC_DB2RH *(volatile unsigned char *)0x53E4 338 | #define ADC_DB2RL *(volatile unsigned char *)0x53E5 339 | #define ADC_DB3RH *(volatile unsigned char *)0x53E6 340 | #define ADC_DB3RL *(volatile unsigned char *)0x53E7 341 | #define ADC_DB4RH *(volatile unsigned char *)0x53E8 342 | #define ADC_DB4RL *(volatile unsigned char *)0x53E9 343 | #define ADC_DB5RH *(volatile unsigned char *)0x53EA 344 | #define ADC_DB5RL *(volatile unsigned char *)0x53EB 345 | #define ADC_DB6RH *(volatile unsigned char *)0x53EC 346 | #define ADC_DB6RL *(volatile unsigned char *)0x53ED 347 | #define ADC_DB7RH *(volatile unsigned char *)0x53EE 348 | #define ADC_DB7RL *(volatile unsigned char *)0x53EF 349 | #define ADC_DB8RH *(volatile unsigned char *)0x53F0 350 | #define ADC_DB8RL *(volatile unsigned char *)0x53F1 351 | #define ADC_DB9RH *(volatile unsigned char *)0x53F2 352 | #define ADC_DB9RL *(volatile unsigned char *)0x53F3 353 | 354 | #define ADC_CSR *(volatile unsigned char *)0x5400 355 | #define ADC_CR1 *(volatile unsigned char *)0x5401 356 | #define ADC_CR2 *(volatile unsigned char *)0x5402 357 | #define ADC_CR3 *(volatile unsigned char *)0x5403 358 | #define ADC_DRH *(volatile unsigned char *)0x5404 359 | #define ADC_DRL *(volatile unsigned char *)0x5405 360 | #define ADC_TDRH *(volatile unsigned char *)0x5406 361 | #define ADC_TDRL *(volatile unsigned char *)0x5407 362 | #define ADC_HTRH *(volatile unsigned char *)0x5408 363 | #define ADC_HTRL *(volatile unsigned char *)0x5409 364 | #define ADC_LTRH *(volatile unsigned char *)0x540A 365 | #define ADC_LTRL *(volatile unsigned char *)0x540B 366 | #define ADC_AWSRH *(volatile unsigned char *)0x540C 367 | #define ADC_AWSRL *(volatile unsigned char *)0x540D 368 | #define ADC_AWCRH *(volatile unsigned char *)0x540E 369 | #define ADC_AWCRL *(volatile unsigned char *)0x540F 370 | 371 | #define ADC_CSR_EOC (1 << 7) 372 | #define ADC_CSR_AWD (1 << 6) 373 | #define ADC_CSR_EOCIE (1 << 5) 374 | #define ADC_CSR_AWDIE (1 << 4) 375 | #define ADC_CSR_CH3 (1 << 3) 376 | #define ADC_CSR_CH2 (1 << 2) 377 | #define ADC_CSR_CH1 (1 << 1) 378 | #define ADC_CSR_CH0 (1 << 0) 379 | 380 | #define ADC_CR1_SPSEL2 (1 << 6) 381 | #define ADC_CR1_SPSEL1 (1 << 5) 382 | #define ADC_CR1_SPSEL0 (1 << 4) 383 | #define ADC_CR1_CONT (1 << 1) 384 | #define ADC_CR1_ADON (1 << 0) 385 | 386 | #define ADC_CR2_EXTTRIG (1 << 6) 387 | #define ADC_CR2_EXTSEL1 (1 << 5) 388 | #define ADC_CR2_EXTSEL0 (1 << 4) 389 | #define ADC_CR2_ALIGN (1 << 3) 390 | #define ADC_CR2_SCAN (1 << 1) 391 | 392 | #define ADC_CR3_DBUF (1 << 7) 393 | #define ADC_CR3_OVR (1 << 6) 394 | 395 | 396 | #define CFG_GCR *(volatile unsigned char *)0x7F60 397 | #define CFG_GCR_SWD ((uint8_t)0x01) /*!< Swim disable bit mask */ 398 | #define CFG_GCR_AL ((uint8_t)0x02) /*!< Activation Level bit mask */ 399 | 400 | #define SWIM_CSR *(volatile unsigned char *)0x7F80 401 | #define SWIM_CSR_PRI (1<<0) 402 | #define SWIM_CSR_HSIT (1<<1) 403 | #define SWIM_CSR_RST (1<<2) 404 | #define SWIM_CSR_OSCOFF (1<<3) 405 | #define SWIM_CSR_HS (1<<4) 406 | #define SWIM_CSR_SWIM_DM (1<<5) 407 | #define SWIM_CSR_NO_ACCESS (1<<6) 408 | #define SWIM_CSR_SAFE_MASK (1<<7) 409 | 410 | #define CLK_SWIMCCR *(volatile unsigned char *)0x50CD 411 | 412 | 413 | /* Interrupt commands */ 414 | /*============================== Interrupts ====================================*/ 415 | #if defined(_RAISONANCE_ ) || defined(__RCSTM8__) 416 | #include 417 | #define enableInterrupts() _rim_() /* enable interrupts */ 418 | #define disableInterrupts() _sim_() /* disable interrupts */ 419 | #define __enable_interrupt() _rim_() /* enable interrupts */ 420 | #define __disable_interrupt() _sim_() /* disable interrupts */ 421 | #define rim() _rim_() /* enable interrupts */ 422 | #define sim() _sim_() /* disable interrupts */ 423 | #define nop() _nop_() /* No Operation */ 424 | #define trap() _trap_() /* Trap (soft IT) */ 425 | #define wfi() _wfi_() /* Wait For Interrupt */ 426 | #define halt() _halt_() /* Halt */ 427 | //#endif /*_RAISONANCE_*/ 428 | #elif defined(_COSMIC_) || defined(__CSMC__) 429 | #define enableInterrupts() {_asm("rim\n");} /* enable interrupts */ 430 | #define disableInterrupts() {_asm("sim\n");} /* disable interrupts */ 431 | #define __enable_interrupt() {_asm("rim\n");} /* enable interrupts */ 432 | #define __disable_interrupt() {_asm("sim\n");} /* disable interrupts */ 433 | #define rim() {_asm("rim\n");} /* enable interrupts */ 434 | #define sim() {_asm("sim\n");} /* disable interrupts */ 435 | #define nop() {_asm("nop\n");} /* No Operation */ 436 | #define trap() {_asm("trap\n");} /* Trap (soft IT) */ 437 | #define wfi() {_asm("wfi\n");} /* Wait For Interrupt */ 438 | #define halt() {_asm("halt\n");} /* Halt */ 439 | //#endif /*_COSMIC_*/ 440 | #elif defined(_IAR_) || defined(__IAR_SYSTEMS_ICC__) 441 | #include 442 | #define enableInterrupts() __enable_interrupt() /* enable interrupts */ 443 | #define disableInterrupts() __disable_interrupt() /* disable interrupts */ 444 | #define rim() __enable_interrupt() /* enable interrupts */ 445 | #define sim() __disable_interrupt() /* disable interrupts */ 446 | #define nop() __no_operation() /* No Operation */ 447 | #define trap() __trap() /* Trap (soft IT) */ 448 | #define wfi() __wait_for_interrupt() /* Wait For Interrupt */ 449 | #define halt() __halt() /* Halt */ 450 | //#endif /*_IAR_*/ 451 | #else /**/ 452 | #define __enable_interrupt() {__asm__("rim\n");} /* enable interrupts */ 453 | #define __disable_interrupt() {__asm__("sim\n");} /* disable interrupts */ 454 | #define rim() {__asm__("rim\n");} /* enable interrupts */ 455 | #define sim() {__asm__("sim\n");} /* disable interrupts */ 456 | #define nop() {__asm__("nop\n");} /* No Operation */ 457 | #define trap() {__asm__("trap\n");} /* Trap (soft IT) */ 458 | #define wfi() {__asm__("wfi\n");} /* Wait For Interrupt */ 459 | #define halt() {__asm__("halt\n");} /* Halt */ 460 | #endif /**/ 461 | 462 | /*============================== Interrupt vector Handling ========================*/ 463 | 464 | #if defined(_COSMIC_) || defined(__CSMC__) 465 | #define ISR(a,b) @far @interrupt void a(void) 466 | #define ISR_TRAP(a) void @far @interrupt a(void) 467 | #define INTERRUPT @far @interrupt 468 | //#endif /* _COSMIC_ */ 469 | #elif defined(_RAISONANCE_) || defined(__RCSTM8__) 470 | #define ISR(a,b) void a(void) interrupt b 471 | #define ISR_TRAP(a) void a(void) trap 472 | //#endif /* _RAISONANCE_ */ 473 | #elif defined(_IAR_) || defined(__IAR_SYSTEMS_ICC__) 474 | #define STRINGVECTOR(x) #x 475 | #define VECTOR_ID(x) STRINGVECTOR( vector = (x) ) 476 | #define ISR( a, b ) \ 477 | _Pragma( VECTOR_ID( (b)+2 ) ) \ 478 | __interrupt void (a)( void ) 479 | #define ISR_TRAP(a) \ 480 | _Pragma( VECTOR_ID( 1 ) ) \ 481 | __interrupt void (a) (void) 482 | #define INTERRUPT __interrupt 483 | //#endif /* _IAR_ */ 484 | #else 485 | #ifndef __SDCC 486 | #define __interrupt(x) 487 | #endif 488 | // Note that the vector counts start from 0, i.e. the (addr_vector - 0x8000) / 4 489 | // In SDCC however, RESET and TRAP are left out in this count, i.e. IRQ0 is at 490 | // address 0x8008. So we use this macro to allow the below vector definitions from 491 | // iostm8s003f3.h to still work. 492 | #define ISR(name,vector) void name(void) __interrupt(vector) 493 | #endif 494 | 495 | /** 496 | * @brief ITC Interrupt Lines selection 497 | */ 498 | typedef enum { 499 | ITC_IRQ_TLI = 0, /*!< Software interrupt */ 500 | ITC_IRQ_AWU = 1, /*!< Auto wake up from halt interrupt */ 501 | ITC_IRQ_CLK = 2, /*!< Clock controller interrupt */ 502 | ITC_IRQ_PORTA = 3, /*!< Port A external interrupts */ 503 | ITC_IRQ_PORTB = 4, /*!< Port B external interrupts */ 504 | ITC_IRQ_PORTC = 5, /*!< Port C external interrupts */ 505 | ITC_IRQ_PORTD = 6, /*!< Port D external interrupts */ 506 | ITC_IRQ_PORTE = 7, /*!< Port E external interrupts */ 507 | 508 | #if defined(STM8S208) || defined(STM8AF52Ax) 509 | ITC_IRQ_CAN_RX = 8, /*!< beCAN RX interrupt */ 510 | ITC_IRQ_CAN_TX = 9, /*!< beCAN TX/ER/SC interrupt */ 511 | #endif /*STM8S208 or STM8AF52Ax */ 512 | 513 | #ifdef STM8S903 514 | ITC_IRQ_PORTF = 8, /*!< Port F external interrupts */ 515 | #endif /*STM8S903*/ 516 | 517 | ITC_IRQ_SPI = 10, /*!< SPI interrupt */ 518 | ITC_IRQ_TIM1_OVF = 11, /*!< TIM1 update/overflow/underflow/trigger/ 519 | break interrupt*/ 520 | ITC_IRQ_TIM1_CAPCOM = 12, /*!< TIM1 capture/compare interrupt */ 521 | 522 | #ifdef STM8S903 523 | ITC_IRQ_TIM5_OVFTRI = 13, /*!< TIM5 update/overflow/underflow/trigger/ 524 | interrupt */ 525 | ITC_IRQ_TIM5_CAPCOM = 14, /*!< TIM5 capture/compare interrupt */ 526 | #else 527 | ITC_IRQ_TIM2_OVF = 13, /*!< TIM2 update /overflow interrupt */ 528 | ITC_IRQ_TIM2_CAPCOM = 14, /*!< TIM2 capture/compare interrupt */ 529 | #endif /*STM8S903*/ 530 | 531 | ITC_IRQ_TIM3_OVF = 15, /*!< TIM3 update /overflow interrupt*/ 532 | ITC_IRQ_TIM3_CAPCOM = 16, /*!< TIM3 update /overflow interrupt */ 533 | ITC_IRQ_UART1_TX = 17, /*!< USART1 TX interrupt */ 534 | ITC_IRQ_UART1_RX = 18, /*!< USART1 RX interrupt */ 535 | ITC_IRQ_I2C = 19, /*!< I2C interrupt */ 536 | 537 | #if defined(STM8S105) || defined(STM8S005) || defined(STM8AF626x) 538 | ITC_IRQ_UART2_TX = 20, /*!< USART2 TX interrupt */ 539 | ITC_IRQ_UART2_RX = 21, /*!< USART2 RX interrupt */ 540 | #endif /*STM8S105 or STM8AF626x */ 541 | 542 | #if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8AF52Ax) || defined(STM8AF62Ax) 543 | ITC_IRQ_UART3_TX = 20, /*!< USART3 TX interrupt */ 544 | ITC_IRQ_UART3_RX = 21, /*!< USART3 RX interrupt */ 545 | ITC_IRQ_ADC2 = 22, /*!< ADC2 interrupt */ 546 | #endif /*STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax */ 547 | 548 | #if defined(STM8S105) || defined(STM8S005) || defined(STM8S103) || defined(STM8S003) || defined(STM8S903) || defined(STM8AF626x) 549 | ITC_IRQ_ADC1 = 22, /*!< ADC2 interrupt */ 550 | #endif /*STM8S105, STM8S103 or STM8S903 or STM8AF626x */ 551 | 552 | #ifdef STM8S903 553 | ITC_IRQ_TIM6_OVFTRI = 23, /*!< TIM6 update/overflow/underflow/trigger/ 554 | interrupt */ 555 | #else 556 | ITC_IRQ_TIM4_OVF = 23, /*!< TIM4 update /overflow interrupt */ 557 | #endif /*STM8S903*/ 558 | 559 | ITC_IRQ_EEPROM_EEC = 24 /*!< Flash interrupt */ 560 | } ITC_Irq_TypeDef; 561 | 562 | #endif // _STH8_H -------------------------------------------------------------------------------- /src/stm8s_conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm8s_conf.h 4 | * @author MCD Application Team 5 | * @version V2.0.4 6 | * @date 26-April-2018 7 | * @brief This file is used to configure the Library. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT 2014 STMicroelectronics

12 | * 13 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 14 | * You may not use this file except in compliance with the License. 15 | * You may obtain a copy of the License at: 16 | * 17 | * http://www.st.com/software_license_agreement_liberty_v2 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | * See the License for the specific language governing permissions and 23 | * limitations under the License. 24 | * 25 | ****************************************************************************** 26 | */ 27 | 28 | /* SDCC patch: include "STM8AF622x" defined in "STM8S_StdPeriph_Tempate" */ 29 | 30 | /* Define to prevent recursive inclusion -------------------------------------*/ 31 | #ifndef __STM8S_CONF_H 32 | #define __STM8S_CONF_H 33 | 34 | /* Includes ------------------------------------------------------------------*/ 35 | #include "stm8s.h" 36 | 37 | /* Exported types ------------------------------------------------------------*/ 38 | /* Exported constants --------------------------------------------------------*/ 39 | /* Uncomment the line below to expanse the "assert_param" macro in the 40 | Standard Peripheral Library drivers code */ 41 | #define USE_FULL_ASSERT (0) 42 | 43 | /* Exported macro ------------------------------------------------------------*/ 44 | #ifdef USE_FULL_ASSERT 45 | 46 | /** 47 | * @brief The assert_param macro is used for function's parameters check. 48 | * @param expr: If expr is false, it calls assert_failed function 49 | * which reports the name of the source file and the source 50 | * line number of the call that failed. 51 | * If expr is true, it returns no value. 52 | * @retval : None 53 | */ 54 | #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) 55 | /* Exported functions ------------------------------------------------------- */ 56 | void assert_failed(uint8_t* file, uint32_t line); 57 | #else 58 | #define assert_param(expr) ((void)0) 59 | #endif /* USE_FULL_ASSERT */ 60 | 61 | #endif /* __STM8S_CONF_H */ 62 | 63 | 64 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -------------------------------------------------------------------------------- /src/timer.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "timer.h" 3 | 4 | // 5 | // Setup Timer 1 to generate a 100 Hz TRG0 based upon a 16 MHz timer. 6 | // 7 | /* From http://blog.mark-stevens.co.uk/2012/09/single-pulse-generation-with-the-stm8s/ */ 8 | void setup_timer1(void) 9 | { 10 | // Enable the Timer 1 clock 11 | SETBIT(CLK_PCKENR1, CLK_PCKENR1_TIM1); 12 | 13 | CLRBIT(TIM1_CR1, TIM_CR1_DIR); // Up counter. 14 | CLRBIT(TIM1_CR1, TIM_CR1_CMSL); // Edge aligned counter. 15 | CLRBIT(TIM1_CR1, TIM_CR1_CMSH); // Edge aligned counter. 16 | 17 | CLRBIT(TIM1_CR2, TIM_CR2_MMS0); // Update event selected as trigger out. 18 | SETBIT(TIM1_CR2, TIM_CR2_MMS1); // Update event selected as trigger out. 19 | CLRBIT(TIM1_CR2, TIM_CR2_MMS2); // Update event selected as trigger out. 20 | 21 | TIM1_RCR = 0; // No repetition. 22 | 23 | TIM1_PSCRH = 0; // Prescaler = 4 24 | TIM1_PSCRL = 3; 25 | 26 | TIM1_ARRH = 0x9c; // High byte of 40,000. 27 | TIM1_ARRL = 0x40; // Low byte of 40,000. 28 | 29 | SETBIT(TIM1_CR1, TIM_CR1_CEN); // Finally enable the timer. 30 | } 31 | 32 | // 33 | // Setup Timer 2 to generate a 400 Hz interrupt based upon a 16 MHz timer. 34 | // 35 | /* From http://blog.mark-stevens.co.uk/2012/08/using-timers-on-the-stm8s/ */ 36 | void setup_timer2(void) 37 | { 38 | // Enable the Timer 2 clock 39 | SETBIT(CLK_PCKENR1, CLK_PCKENR1_TIM2); 40 | 41 | TIM2_PSCR = 0x00; // Prescaler = 1. 42 | TIM2_ARRH = 0x9c; // High byte of 40,000. 43 | TIM2_ARRL = 0x40; // Low byte of 40,000. 44 | 45 | SETBIT(TIM2_IER, TIM_IER_UIE); // Enable the update interrupts. 46 | SETBIT(TIM2_CR1, TIM_CR1_CEN); // Finally enable the timer. 47 | } -------------------------------------------------------------------------------- /src/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef __TIMER_H 2 | #define __TIMER_H 3 | 4 | void setup_timer1(void); 5 | void setup_timer2(void); 6 | 7 | #endif /* __TIMER_H */ --------------------------------------------------------------------------------