├── .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 */
--------------------------------------------------------------------------------