├── docs
├── ireg.png
├── vreg.png
├── 74HC_HCT595.pdf
├── TopBoardSide1.jpg
├── TopBoardSide2.jpg
├── 74HC595_TSSOP16.png
├── BottomBoardSide1.jpg
├── BottomBoardSide2.jpg
├── control_pinouts.png
├── STM8S003F3 pinout.png
├── B3603_BoardSchematics.pdf
├── B3603_TopBoardSchematics.png
├── B3603_BottomBoardSchematics.pdf
├── B3603_BottomBoardSchematics.png
├── DM00024550_STM8S003F3_Datasheet.pdf
├── BottomBoardPartialReverseEngineering.jpg
├── CD00190271_RM0016_STM8_Reference_manual.pdf
├── CD00191343_programming_STM8_flash_eeprom.pdf
└── links
├── stm8
├── .gitignore
├── eeprom.h
├── parse.h
├── display.h
├── outputs.h
├── adc.h
├── fixedpoint.c
├── uart.h
├── Makefile
├── test_adc_accuracy.c
├── test_pwm_accuracy.c
├── fixedpoint.h
├── test_parse.c
├── parse.c
├── config.h
├── adc.c
├── eeprom.c
├── display.c
├── test_pwm_accuracy.py
├── config.c
├── outputs.c
├── PROTOCOL.md
├── uart.c
├── calibrate.py
├── stm8s.h
├── main.c
└── COPYING
├── README.md
└── LICENSE
/docs/ireg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/ireg.png
--------------------------------------------------------------------------------
/docs/vreg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/vreg.png
--------------------------------------------------------------------------------
/docs/74HC_HCT595.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/74HC_HCT595.pdf
--------------------------------------------------------------------------------
/docs/TopBoardSide1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/TopBoardSide1.jpg
--------------------------------------------------------------------------------
/docs/TopBoardSide2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/TopBoardSide2.jpg
--------------------------------------------------------------------------------
/docs/74HC595_TSSOP16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/74HC595_TSSOP16.png
--------------------------------------------------------------------------------
/docs/BottomBoardSide1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/BottomBoardSide1.jpg
--------------------------------------------------------------------------------
/docs/BottomBoardSide2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/BottomBoardSide2.jpg
--------------------------------------------------------------------------------
/docs/control_pinouts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/control_pinouts.png
--------------------------------------------------------------------------------
/docs/STM8S003F3 pinout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/STM8S003F3 pinout.png
--------------------------------------------------------------------------------
/docs/B3603_BoardSchematics.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/B3603_BoardSchematics.pdf
--------------------------------------------------------------------------------
/docs/B3603_TopBoardSchematics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/B3603_TopBoardSchematics.png
--------------------------------------------------------------------------------
/docs/B3603_BottomBoardSchematics.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/B3603_BottomBoardSchematics.pdf
--------------------------------------------------------------------------------
/docs/B3603_BottomBoardSchematics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/B3603_BottomBoardSchematics.png
--------------------------------------------------------------------------------
/docs/DM00024550_STM8S003F3_Datasheet.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/DM00024550_STM8S003F3_Datasheet.pdf
--------------------------------------------------------------------------------
/docs/BottomBoardPartialReverseEngineering.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/BottomBoardPartialReverseEngineering.jpg
--------------------------------------------------------------------------------
/docs/CD00190271_RM0016_STM8_Reference_manual.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/CD00190271_RM0016_STM8_Reference_manual.pdf
--------------------------------------------------------------------------------
/docs/CD00191343_programming_STM8_flash_eeprom.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baruch/b3603/HEAD/docs/CD00191343_programming_STM8_flash_eeprom.pdf
--------------------------------------------------------------------------------
/stm8/.gitignore:
--------------------------------------------------------------------------------
1 | *.rel
2 | *.ihx
3 | *.lk
4 | *.map
5 | *.rst
6 | *.lst
7 | *.asm
8 | *.sym
9 | .*.d
10 | test_pwm_accuracy
11 | test_adc_accuracy
12 | test_parse
13 | .*
14 |
--------------------------------------------------------------------------------
/docs/links:
--------------------------------------------------------------------------------
1 | Review of the B3603 with lots of data about its parts:
2 | http://www.eevblog.com/forum/reviews/b3603-dcdc-buck-converter-mini-review-and-how-the-set-key-could-be-fatal/
3 |
4 | Hints about the 3461AH 7-segment 4-digit display:
5 | http://forum.arduino.cc/index.php?topic=139675.0
6 | (34 = 3.4" 7 segment, 61 = specific type, A is common cathode)
7 |
--------------------------------------------------------------------------------
/stm8/eeprom.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include
20 |
21 | uint8_t eeprom_set_afr0(void);
22 | uint8_t eeprom_save_data(uint8_t *dst, uint8_t *src, uint8_t len);
23 |
--------------------------------------------------------------------------------
/stm8/parse.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #ifndef PARSE_H
20 | #define PARSE_H
21 |
22 | #include
23 |
24 | uint16_t parse_millinum(uint8_t *s);
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/stm8/display.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include
20 |
21 | void display_refresh(void);
22 | void display_show(uint8_t ch1, uint8_t dot1, uint8_t ch2, uint8_t dot2, uint8_t ch3, uint8_t dot3, uint8_t ch4, uint8_t dot4);
23 |
--------------------------------------------------------------------------------
/stm8/outputs.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #ifndef OUTPUTS_H
20 | #define OUTPUTS_H
21 |
22 | #include
23 |
24 | #include "config.h"
25 |
26 | void pwm_init(void);
27 | void output_commit(cfg_output_t *cfg, cfg_system_t *sys, uint8_t state_constant_current);
28 | void output_check_state(cfg_system_t *sys, uint8_t state_constant_current);
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/stm8/adc.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #ifndef ADC_H
20 | #define ADC_H
21 |
22 | #include
23 | #include "fixedpoint.h"
24 | #include "config.h"
25 |
26 | void adc_init(void);
27 | void adc_start(uint8_t channel);
28 | fixed_t adc_to_volt(uint16_t adc, calibrate_t *cal);
29 | uint16_t adc_read(void);
30 | uint8_t adc_channel(void);
31 | uint8_t adc_ready(void);
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/stm8/fixedpoint.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include "fixedpoint.h"
20 |
21 | /* For better accuracy we round to the nearest number, either up or down.
22 | * We save one extra bit temporarily and if it is 1 we round up and if it is 0
23 | * we round down.
24 | */
25 | uint32_t fixed_round(uint32_t x)
26 | {
27 | uint8_t round;
28 |
29 | x >>= FIXED_SHIFT-1;
30 |
31 | round = x&1;
32 | x >>= 1;
33 |
34 | return x+round;
35 | }
36 |
--------------------------------------------------------------------------------
/stm8/uart.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include
20 |
21 | extern uint8_t uart_read_buf[64];
22 | extern uint8_t uart_read_len;
23 | extern uint8_t read_newline;
24 |
25 | void uart_init(void);
26 | void uart_write_ch(const char ch);
27 | void uart_write_str(const char *str);
28 | void uart_write_int(uint16_t val);
29 | void uart_write_int32(uint32_t val);
30 | void uart_write_fixed_point(uint32_t val);
31 | void uart_write_millivolt(uint16_t val);
32 | void uart_write_milliamp(uint16_t val);
33 | void uart_drive(void);
34 | void uart_flush_writes(void);
35 |
--------------------------------------------------------------------------------
/stm8/Makefile:
--------------------------------------------------------------------------------
1 | SRC=main.c display.c uart.c eeprom.c outputs.c config.c fixedpoint.c parse.c adc.c
2 | CFLAGS= -lstm8 -mstm8 --opt-code-size --std-c99
3 | OBJ=$(SRC:.c=.rel)
4 | DEP=$(SRC:%.c=.%.c.d)
5 |
6 | V=0
7 |
8 | ACTUAL_SDCC=sdcc $(CFLAGS)
9 | SDCC_0 = @echo SDCC $<; $(ACTUAL_SDCC)
10 | SDCC_1 = $(ACTUAL_SDCC)
11 | SDCC = $(SDCC_$(V))
12 |
13 | LINK_0 = @echo LINK $@; $(ACTUAL_SDCC)
14 | LINK_1 = $(ACTUAL_SDCC)
15 | LINK = $(LINK_$(V))
16 |
17 | all: b3603.ihx check_size
18 |
19 | -include $(DEP)
20 |
21 | check_size: b3603.ihx
22 | @CODESIZE=$$(grep '^CODE' b3603.map |head -n1 | sed -e 's/^.*=\s*\([0-9]\+\).*$$/\1/'); \
23 | if [ "$$CODESIZE" -gt 8192 ]; then echo "Code is too large, it is $$CODESIZE bytes"; exit 1; \
24 | else echo "Code fits the flash, it is $$CODESIZE"; \
25 | fi
26 |
27 | b3603.ihx: $(OBJ)
28 | $(LINK) --out-fmt-ihx --code-size 8192 -o $@ $^
29 |
30 | %.rel: %.c
31 | @$(SDCC) -M $< > .$<.tmp.d
32 | @mv .$<.tmp.d .$<.d
33 | $(SDCC) -c -o $@ $<
34 |
35 | test_pwm_accuracy: test_pwm_accuracy.c outputs.c config.c fixedpoint.c
36 | gcc -g -Wall -o $@ $< -DTEST=1
37 |
38 | test_adc_accuracy: test_adc_accuracy.c config.c adc.c fixedpoint.c
39 | gcc -g -Wall -o $@ $< -DTEST=1
40 |
41 | test_parse: test_parse.c parse.c
42 | gcc -g -Wall -o $@ $< -DTEST=1
43 |
44 | clean:
45 | -rm -f *.rel *.ihx *.lk *.map *.rst *.lst *.asm *.sym .*.d
46 |
47 | .PHONY: all clean check_size
48 |
--------------------------------------------------------------------------------
/stm8/test_adc_accuracy.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include
20 |
21 | void uart_write_ch(const char ch) { (void)ch; }
22 | void uart_write_str(const char *s) { (void)s; }
23 |
24 |
25 | #include "fixedpoint.c"
26 | #include "adc.c"
27 | #include "eeprom.c"
28 | #include "config.c"
29 |
30 | #include
31 |
32 | int main()
33 | {
34 | uint16_t adc;
35 | uint16_t mvolt;
36 | cfg_system_t sys;
37 |
38 | config_load_system(&sys);
39 |
40 | for (adc = 0; adc < 8192; adc++) {
41 | mvolt = adc_to_volt(adc, &(sys.vin_adc));
42 | printf("%u %u %u.%03u\n", adc, mvolt, mvolt/1000, mvolt%1000);
43 | }
44 | return 0;
45 | }
46 |
--------------------------------------------------------------------------------
/stm8/test_pwm_accuracy.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include
20 |
21 | void uart_write_ch(const char ch) { (void)ch; }
22 | void uart_write_str(const char *s) { (void)s; }
23 | void uart_write_int(uint16_t v) { (void)v; }
24 |
25 | #include "fixedpoint.c"
26 | #include "outputs.c"
27 | #include "eeprom.c"
28 | #include "config.c"
29 |
30 | #include
31 |
32 | int main()
33 | {
34 | uint16_t val;
35 | uint16_t pwm;
36 | cfg_system_t sys;
37 |
38 | config_load_system(&sys);
39 |
40 | for (val = 10; val < 35000; val+=10) {
41 | pwm = pwm_from_set(val, &(sys.vout_pwm));
42 | printf("%u %u.%03u %u %.2f\n", val, val/1000, val % 1000, pwm, ((double)pwm)/8191.0*100.0);
43 | }
44 | return 0;
45 | }
46 |
--------------------------------------------------------------------------------
/stm8/fixedpoint.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #ifndef FIXEDPOINT_H
20 | #define FIXEDPOINT_H
21 |
22 | #include
23 |
24 | typedef uint16_t fixed_t;
25 |
26 | /* The FLOAT_TO_FIXED(f) macro takes a float number and converts it to a fixed
27 | * point number with FIXED_SHIFT bits fraction part.
28 | *
29 | * To make sure we are as close as possible we also handle the rounding
30 | * properly by adding one extra bit and if it is 1 we will round up, if it is 0
31 | * we will round down.
32 | */
33 | #define FIXED_SHIFT 16
34 | #define FIXED_FRACTION_MASK (uint32_t)(((1LU)<> 1) + FLOAT_TO_FIXED_ROUNDING(f))
38 | uint32_t fixed_round(uint32_t x);
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/stm8/test_parse.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include
20 |
21 | void uart_write_ch(const char ch) { (void)ch; }
22 | void uart_write_str(const char *s) { (void)s; }
23 |
24 | #include "parse.c"
25 |
26 | #include
27 |
28 | #define TEST_PARSE(s, expected) if (parse_millinum((uint8_t*)s) != expected) { printf("Parsing of %s yielded %u but expected %u\n", s, parse_millinum((uint8_t*)s), expected);}
29 |
30 | int main()
31 | {
32 | TEST_PARSE("3.3", 3300);
33 | TEST_PARSE("3.30", 3300);
34 | TEST_PARSE("3.300", 3300);
35 |
36 | TEST_PARSE("5", 5000);
37 | TEST_PARSE("5.0", 5000);
38 | TEST_PARSE("5.00", 5000);
39 | TEST_PARSE("5.000", 5000);
40 |
41 | TEST_PARSE("0.001", 1);
42 | TEST_PARSE("0.010", 10);
43 | TEST_PARSE("0.100", 100);
44 | TEST_PARSE("1.111", 1111);
45 |
46 | TEST_PARSE("0.009", 9);
47 | TEST_PARSE("0.090", 90);
48 | TEST_PARSE("0.900", 900);
49 | TEST_PARSE("9.999", 9999);
50 |
51 | return 0;
52 | }
53 |
--------------------------------------------------------------------------------
/stm8/parse.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include "parse.h"
20 | #include "uart.h"
21 |
22 | uint16_t parse_num(uint8_t *s, uint8_t **stop, uint8_t *digits_seen)
23 | {
24 | uint8_t digit;
25 | uint16_t num = 0;
26 |
27 | *digits_seen = 0;
28 |
29 | for (; *s >= '0' && *s <= '9'; s++) {
30 | digit = *s - '0';
31 | num *= 10;
32 | num += digit;
33 | (*digits_seen)++;
34 | }
35 |
36 | *stop = s;
37 | return num;
38 | }
39 |
40 | uint16_t parse_millinum(uint8_t *s)
41 | {
42 | uint8_t *t = s;
43 | uint8_t *stop;
44 | uint32_t fraction_digits = 0;
45 | uint16_t whole_digits = 0;
46 | uint8_t digits_seen;
47 |
48 | whole_digits = parse_num(s, &stop, &digits_seen);
49 | if (whole_digits > 62 || digits_seen > 2)
50 | goto invalid_number;
51 |
52 | whole_digits *= 1000;
53 |
54 | if (*stop == '\0')
55 | return whole_digits;
56 |
57 | if (*stop != '.')
58 | goto invalid_number;
59 |
60 | fraction_digits = parse_num(stop+1, &stop, &digits_seen);
61 | if (fraction_digits > 999 || digits_seen > 3)
62 | goto invalid_number;
63 |
64 | if (digits_seen == 1)
65 | fraction_digits *= 100;
66 | else if (digits_seen == 2)
67 | fraction_digits *= 10;
68 |
69 | return whole_digits + fraction_digits;
70 |
71 | invalid_number:
72 | uart_write_str("INVALID NUMBER '");
73 | uart_write_str(t);
74 | uart_write_ch('\'');
75 | uart_write_str("\r\n");
76 | return 0xFFFF;
77 | }
78 |
--------------------------------------------------------------------------------
/stm8/config.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #ifndef CONFIG_H
20 | #define CONFIG_H
21 |
22 | #include
23 | #include "fixedpoint.h"
24 |
25 | typedef struct {
26 | uint8_t version;
27 | uint16_t vset; // mV
28 | uint16_t cset; // mA
29 | uint16_t vshutdown; // mV
30 | uint16_t cshutdown; // mA
31 | } cfg_output_t;
32 |
33 | // These parameters correspond to the linear formula:
34 | // y = a*x + b
35 | // where a and b are the coefficients, x is the input and y the calculated output
36 | typedef struct {
37 | uint32_t a;
38 | uint32_t b;
39 | } calibrate_t;
40 |
41 | typedef struct {
42 | uint8_t version;
43 | uint8_t name[17];
44 | uint8_t default_on;
45 | uint8_t output;
46 | uint8_t autocommit;
47 |
48 | calibrate_t vin_adc;
49 | calibrate_t vout_adc;
50 | calibrate_t cout_adc;
51 |
52 | calibrate_t vout_pwm;
53 | calibrate_t cout_pwm;
54 | } cfg_system_t;
55 |
56 | typedef struct {
57 | uint16_t vin_raw;
58 | uint16_t vout_raw;
59 | uint16_t cout_raw;
60 | uint16_t vin; // mV
61 | uint16_t vout; // mV
62 | uint16_t cout; // mA
63 | uint8_t constant_current; // If false, we are in constant voltage
64 | uint8_t pc3;
65 | } state_t;
66 |
67 | void config_load_system(cfg_system_t *sys);
68 | void config_save_system(cfg_system_t *sys);
69 | void config_default_system(cfg_system_t *sys);
70 | void config_load_output(cfg_output_t *cfg);
71 | void config_save_output(cfg_output_t *cfg);
72 | void config_default_output(cfg_output_t *cfg);
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/stm8/adc.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include "adc.h"
20 | #include "stm8s.h"
21 |
22 | static uint32_t sum;
23 | static uint8_t count;
24 |
25 | void adc_init(void)
26 | {
27 | ADC1_CR1 = 0x70; // Power down, clock/18
28 | ADC1_CR2 = 0x08; // Right alignment
29 | ADC1_CR3 = 0x00;
30 | ADC1_CSR = 0x00;
31 |
32 | ADC1_TDRL = 0x0F;
33 |
34 | ADC1_CR1 |= 0x01; // Turn on the ADC
35 | }
36 |
37 | inline void _adc_start(void)
38 | {
39 | ADC1_CSR &= 0x7F; // Turn off EOC
40 | ADC1_CR1 |= 1; // Trigger conversion
41 | }
42 |
43 | void adc_start(uint8_t channel)
44 | {
45 | uint8_t csr = ADC1_CSR;
46 | csr &= 0x70; // Turn off EOC, Clear Channel
47 | csr |= channel; // Select channel
48 | ADC1_CSR = csr;
49 |
50 | ADC1_CR1 |= 1; // Trigger conversion
51 |
52 | sum = 0;
53 | count = 0;
54 | }
55 |
56 | fixed_t adc_to_volt(uint16_t adc, calibrate_t *cal)
57 | {
58 | uint32_t tmp;
59 |
60 | tmp = adc * cal->a;
61 |
62 | if (tmp > cal->b)
63 | tmp -= cal->b;
64 | else
65 | tmp = 0;
66 |
67 | return fixed_round(tmp);
68 | }
69 |
70 | inline uint16_t _adc_read(void)
71 | {
72 | uint16_t val = ADC1_DRL;
73 | uint16_t valh = ADC1_DRH;
74 |
75 | return val | (valh<<8);
76 | }
77 |
78 | uint16_t adc_read(void)
79 | {
80 | return sum/8;
81 | }
82 |
83 | uint8_t adc_channel(void)
84 | {
85 | return ADC1_CSR & 0x0F;
86 | }
87 |
88 | uint8_t adc_ready(void)
89 | {
90 | if (ADC1_CSR & 0x80) {
91 | sum += _adc_read();
92 | count++;
93 | if (count < 64) {
94 | _adc_start();
95 | return 0;
96 | } else {
97 | return 1;
98 | }
99 | }
100 | return 0;
101 | }
102 |
--------------------------------------------------------------------------------
/stm8/eeprom.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include "eeprom.h"
20 | #include "stm8s.h"
21 |
22 | static uint8_t eeprom_unlock_data(void)
23 | {
24 | FLASH_DUKR = 0xAE; // Enable the flash data writing
25 | FLASH_DUKR = 0x56;
26 |
27 | return (FLASH_IAPSR & FLASH_IAPSR_DUL); // True if device unlocked
28 | }
29 |
30 | inline void eeprom_lock(void)
31 | {
32 | FLASH_IAPSR &= ~FLASH_IAPSR_DUL;
33 | }
34 |
35 | uint8_t eeprom_set_afr0(void)
36 | {
37 | uint8_t sr;
38 | uint16_t timeout = 0xFFFF;
39 |
40 | if (!eeprom_unlock_data())
41 | return 0;
42 |
43 | FLASH_CR2 = FLASH_CR2_OPT;// Set the OPT bit
44 | FLASH_NCR2 = ~FLASH_NCR2_NOPT; // Remove the NOPT bit
45 |
46 | OPT2 = 1;
47 | NOPT2 = 0xFE;
48 | for (timeout = 0xFFFF; timeout > 0; timeout--) {
49 | sr = FLASH_IAPSR;
50 | if (sr & FLASH_IAPSR_EOP)
51 | break;
52 | }
53 |
54 | if (sr & FLASH_IAPSR_WR_PG_DIS)
55 | timeout = 0; // This will report failure
56 |
57 | FLASH_CR2 &= FLASH_CR2_OPT;
58 | FLASH_NCR2 |= FLASH_NCR2_NOPT;
59 | eeprom_lock();
60 | return (timeout > 0) && (OPT2 & 1);
61 | }
62 |
63 | uint8_t eeprom_save_data(uint8_t *dst, uint8_t *src, uint8_t len)
64 | {
65 | uint16_t timeout;
66 | uint8_t sr;
67 |
68 | if (!eeprom_unlock_data())
69 | return 0;
70 |
71 | for (; len > 0; len--, dst++, src++) {
72 | *dst = *src;
73 | IWDG_KR = 0xAA; // Reset the counter
74 | }
75 |
76 | for (timeout = 0xFFFF; timeout > 0; timeout--) {
77 | IWDG_KR = 0xAA; // Reset the counter
78 | sr = FLASH_IAPSR;
79 | if (sr & FLASH_IAPSR_EOP)
80 | break;
81 | }
82 |
83 | if (sr & FLASH_IAPSR_WR_PG_DIS)
84 | timeout = 0; // This will report failure
85 |
86 | eeprom_lock();
87 | return (timeout > 0);
88 | }
89 |
--------------------------------------------------------------------------------
/stm8/display.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include "display.h"
20 | #include "stm8s.h"
21 |
22 | #include
23 |
24 | uint8_t display_idx;
25 | uint8_t display_data[4];
26 | uint8_t pending_display_data[4];
27 | uint8_t pending_update;
28 | uint16_t timer;
29 |
30 | static const display_number[10] = {
31 | 0xFC, // '0'
32 | 0x60, // '1'
33 | 0xDA, // '2'
34 | 0xF2, // '3'
35 | 0x66, // '4'
36 | 0xB6, // '5'
37 | 0xBE, // '6'
38 | 0xE0, // '7'
39 | 0xFE, // '8'
40 | 0xF6, // '9'
41 | };
42 |
43 | #define SET_DATA(bit) do { if (bit) { PD_ODR |= (1<<4); } else { PD_ODR &= ~(1<<4); }} while (0)
44 | #define PULSE_CLOCK() do { PA_ODR |= (1<<1); PA_ODR &= ~(1<<1); } while (0)
45 | #define SAVE_DATA() do { PA_ODR &= ~(1<<2); PA_ODR |= (1<<2); } while (0)
46 |
47 | inline void display_word(uint16_t word)
48 | {
49 | uint8_t i;
50 |
51 | for (i = 0; i < 16; i++) {
52 | uint8_t bit = word & 1;
53 | word >>= 1;
54 | SET_DATA(bit);
55 | PULSE_CLOCK();
56 | }
57 | SAVE_DATA();
58 | }
59 |
60 | void display_refresh(void)
61 | {
62 | int i = display_idx++;
63 | uint8_t bit = 8+(i*2);
64 | uint16_t digit = 0xFF00 ^ (3< 0)
67 | timer--;
68 | if (pending_update && timer == 0) {
69 | memcpy(display_data, pending_display_data, sizeof(display_data));
70 | pending_update = 0;
71 | timer = 1500; // 1/2 of a second, approximately
72 | }
73 |
74 | display_word(digit | display_data[i]);
75 |
76 | if (display_idx == 4)
77 | display_idx = 0;
78 | }
79 |
80 | uint8_t display_char(uint8_t ch, uint8_t dot)
81 | {
82 | if (dot)
83 | dot = 1;
84 | if (ch >= '0' && ch <= '9')
85 | return display_number[ch-'0'] | dot;
86 | return dot;
87 | }
88 |
89 | void display_show(uint8_t ch1, uint8_t dot1, uint8_t ch2, uint8_t dot2, uint8_t ch3, uint8_t dot3, uint8_t ch4, uint8_t dot4)
90 | {
91 | pending_display_data[3] = display_char(ch1, dot1);
92 | pending_display_data[2] = display_char(ch2, dot2);
93 | pending_display_data[1] = display_char(ch3, dot3);
94 | pending_display_data[0] = display_char(ch4, dot4);
95 | pending_update = 1;
96 | }
97 |
--------------------------------------------------------------------------------
/stm8/test_pwm_accuracy.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | import serial
4 | import sys
5 | import time
6 | import csv
7 | import os
8 |
9 | s = serial.Serial('/dev/ttyUSB0', baudrate=38400, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=2)
10 | assert s.isOpen()
11 |
12 | def get_multimeter_sample():
13 | p = os.popen('sigrok-cli -d mastech-ms8250b:conn=/dev/ttyUSB2 --samples 1')
14 | s = p.read()
15 | p.close()
16 | return s.split(' ')[1]
17 |
18 | def ser_write(data):
19 | for d in data:
20 | s.write(d)
21 | time.sleep(0.01)
22 | time.sleep(0.1)
23 |
24 | # Clear previous buffer
25 | while s.read() != '':
26 | pass
27 |
28 | def command(cmd):
29 | ser_write("%s\n" % cmd)
30 | data = ''
31 | while 1:
32 | a = s.read()
33 | if a == '':
34 | break
35 | else:
36 | data += a
37 | lines = [line.strip() for line in data.split('\r')]
38 | return lines
39 |
40 | def status():
41 | lines = command("STATUS")
42 | output = 'UNKNOWN'
43 | vin = 0
44 | vout = 0
45 | cout = 0
46 | constant = 'UNKNOWN'
47 |
48 | for line in lines:
49 | part = line.split(':')
50 | if part[0] == 'OUTPUT':
51 | output = part[1].strip()
52 | elif part[0] == 'VOLTAGE IN':
53 | vin = float(part[1].strip())
54 | elif part[0] == 'VOLTAGE OUT':
55 | vout = float(part[1].strip())
56 | elif part[0] == 'CURRENT OUT':
57 | cout = float(part[1].strip())
58 | elif part[0] == 'CONSTANT':
59 | constant = part[1].strip()
60 |
61 | return dict(output=output, vin=vin, vout=vout, cout=cout, constant=constant)
62 |
63 | def rstatus():
64 | lines = command("RSTATUS")
65 | output = 'UNKNOWN'
66 | vin = 0
67 | vout = 0
68 | cout = 0
69 | constant = 'UNKNOWN'
70 |
71 | for line in lines:
72 | part = line.split(':')
73 | if part[0] == 'OUTPUT':
74 | output = part[1].strip()
75 | elif part[0] == 'VOLTAGE IN ADC':
76 | vin = float(part[1].strip())
77 | elif part[0] == 'VOLTAGE OUT ADC':
78 | vout = float(part[1].strip())
79 | elif part[0] == 'CURRENT OUT ADC':
80 | cout = float(part[1].strip())
81 | elif part[0] == 'CONSTANT':
82 | constant = part[1].strip()
83 |
84 | return dict(output=output, vin_adc=vin, vout_adc=vout, cout_adc=cout, constant=constant)
85 |
86 |
87 | def output_on():
88 | command("OUTPUT 1")
89 |
90 | def output_off():
91 | command("OUTPUT 0")
92 |
93 | def voltage(v):
94 | command("VOLTAGE %.2f" % v)
95 |
96 | def current(c):
97 | command("CURRENT %.3f" % c)
98 |
99 |
100 | voltage(0.01)
101 | current(0.01)
102 | output_on()
103 | csvf = csv.writer(sys.stdout)
104 | csvf.writerow(['set voltage', 'read voltage', 'adc voltage', 'multimeter'])
105 |
106 | for v in range(100, 700, 1):
107 | v1 = v / 100.0
108 | voltage(v1)
109 | time.sleep(2)
110 | t = status()
111 | r = rstatus()
112 | m = get_multimeter_sample()
113 | csvf.writerow([v1, t['vout'], r['vout_adc'], m])
114 | sys.stdout.flush()
115 |
116 | output_off()
117 | s.close()
118 |
--------------------------------------------------------------------------------
/stm8/config.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include "config.h"
20 | #include "eeprom.h"
21 | #include "fixedpoint.h"
22 |
23 | #include
24 |
25 | #define SYSTEM_CONFIG ((cfg_system_t *)0x4000)
26 | #define OUTPUT_CONFIG ((cfg_output_t *)0x4040)
27 |
28 | #define SYSTEM_CFG_VERSION 2
29 | #define OUTPUT_CFG_VERSION 1
30 |
31 | #define DEFAULT_NAME_STR "Unnamed"
32 |
33 | cfg_system_t default_cfg_system = {
34 | .version = SYSTEM_CFG_VERSION,
35 | .name = "Unnamed",
36 | .default_on = 0,
37 | .output = 0,
38 | .autocommit = 1,
39 |
40 | .vin_adc = { .a = FLOAT_TO_FIXED(16*3.3/8.0), .b = 0 },
41 | .vout_adc = { .a = FLOAT_TO_FIXED(3.3/0.073/8.0), .b = FLOAT_TO_FIXED(452) },
42 | .cout_adc = { .a = FLOAT_TO_FIXED(3.3*1.25/8.0), .b = FLOAT_TO_FIXED(200) },
43 | .vout_pwm = { .a = FLOAT_TO_FIXED(8*0.073/3.3), .b = FLOAT_TO_FIXED(33) },
44 | .cout_pwm = { .a = FLOAT_TO_FIXED(8*0.8/3.3), .b = FLOAT_TO_FIXED(160) },
45 | };
46 |
47 | cfg_output_t default_cfg_output = {
48 | OUTPUT_CFG_VERSION,
49 | 5000, // 5V
50 | 500, // 0.5A
51 | 0,
52 | 0,
53 | };
54 |
55 | void config_default_system(cfg_system_t *sys)
56 | {
57 | memcpy(sys, &default_cfg_system, sizeof(default_cfg_system));
58 | }
59 |
60 | inline void validate_system_config(cfg_system_t *sys)
61 | {
62 | if (sys->version != SYSTEM_CFG_VERSION ||
63 | sys->name[0] ||
64 | sys->vin_adc.a ||
65 | sys->vout_adc.a ||
66 | sys->cout_adc.a ||
67 | sys->vout_pwm.a ||
68 | sys->cout_pwm.a
69 | )
70 | {
71 | config_default_system(sys);
72 | // TODO: If we want easy upgradability we can implement it here to
73 | // upgrade from an old struct to a new one.
74 | }
75 | }
76 |
77 | void config_load_system(cfg_system_t *sys)
78 | {
79 | #if TEST
80 | memset(sys, 0, sizeof(*sys));
81 | #else
82 | memcpy(sys, SYSTEM_CONFIG, sizeof(*sys));
83 | #endif
84 | validate_system_config(sys);
85 | }
86 |
87 | void config_save_system(cfg_system_t *sys)
88 | {
89 | eeprom_save_data((uint8_t*)SYSTEM_CONFIG, (uint8_t*)sys, sizeof(*sys));
90 | }
91 |
92 | void config_default_output(cfg_output_t *cfg)
93 | {
94 | memcpy(cfg, &default_cfg_output, sizeof(default_cfg_output));
95 | }
96 |
97 | inline void validate_output_config(cfg_output_t *cfg)
98 | {
99 | if (cfg->version != OUTPUT_CFG_VERSION || cfg->vset == 0 || cfg->cset == 0) {
100 | config_default_output(cfg);
101 | }
102 | }
103 |
104 | void config_load_output(cfg_output_t *cfg)
105 | {
106 | #if TEST
107 | memset(cfg, 0, sizeof(*cfg));
108 | #else
109 | memcpy(cfg, OUTPUT_CONFIG, sizeof(*cfg));
110 | #endif
111 | validate_output_config(cfg);
112 | }
113 |
114 | void config_save_output(cfg_output_t *cfg)
115 | {
116 | eeprom_save_data((uint8_t*)OUTPUT_CONFIG, (uint8_t*)cfg, sizeof(*cfg));
117 | }
118 |
--------------------------------------------------------------------------------
/stm8/outputs.c:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015 Baruch Even
2 | *
3 | * This file is part of the B3603 alternative firmware.
4 | *
5 | * B3603 alternative firmware is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * B3603 alternative firmware is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with B3603 alternative firmware. If not, see .
17 | */
18 |
19 | #include "outputs.h"
20 | #include "fixedpoint.h"
21 | #include "uart.h"
22 |
23 | #include "stm8s.h"
24 |
25 | #define PWM_VAL 0x2000
26 | #define PWM_HIGH (PWM_VAL >> 8)
27 | #define PWM_LOW (PWM_VAL & 0xFF)
28 |
29 | void pwm_init(void)
30 | {
31 | /* Timer 1 Channel 1 for Iout control */
32 | TIM1_CR1 = 0x10; // Down direction
33 | TIM1_ARRH = PWM_HIGH; // Reload counter = 16384
34 | TIM1_ARRL = PWM_LOW;
35 | TIM1_PSCRH = 0; // Prescaler 0 means division by 1
36 | TIM1_PSCRL = 0;
37 | TIM1_RCR = 0; // Continuous
38 |
39 | TIM1_CCMR1 = 0x70; // Set up to use PWM mode 2.
40 | TIM1_CCER1 = 0x03; // Output is enabled for channel 1, active low
41 | TIM1_CCR1H = 0x00; // Start with the PWM signal off
42 | TIM1_CCR1L = 0x00;
43 |
44 | TIM1_BKR = 0x80; // Enable the main output.
45 |
46 | /* Timer 2 Channel 1 for Vout control */
47 | TIM2_ARRH = PWM_HIGH; // Reload counter = 16384
48 | TIM2_ARRL = PWM_LOW;
49 | TIM2_PSCR = 0; // Prescaler 0 means division by 1
50 | TIM2_CR1 = 0x00;
51 |
52 | TIM2_CCMR1 = 0x70; // Set up to use PWM mode 2.
53 | TIM2_CCER1 = 0x03; // Output is enabled for channel 1, active low
54 | TIM2_CCR1H = 0x00; // Start with the PWM signal off
55 | TIM2_CCR1L = 0x00;
56 |
57 | // Timers are still off, will be turned on when output is turned on
58 | }
59 |
60 | inline void cvcc_led_cc(void)
61 | {
62 | PA_ODR |= (1<<3);
63 | PA_DDR |= (1<<3);
64 | }
65 |
66 | inline void cvcc_led_cv(void)
67 | {
68 | PA_ODR &= ~(1<<3);
69 | PA_DDR |= (1<<3);
70 | }
71 |
72 | inline void cvcc_led_off(void)
73 | {
74 | PA_DDR &= ~(1<<3);
75 | }
76 |
77 | uint16_t pwm_from_set(fixed_t set, calibrate_t *cal)
78 | {
79 | uint32_t tmp;
80 |
81 | // x*a
82 | tmp = set * cal->a;
83 |
84 | // x*a + b
85 | tmp += cal->b;
86 |
87 | // PWM is 0x8000 and as such amounts to a shift by 13 so to multiple by PWM
88 | // we simply shift all calculations by 3 and this avoids overflows and loss
89 | // of precision.
90 |
91 | return fixed_round(tmp);
92 | }
93 |
94 | inline void control_voltage(cfg_output_t *cfg, cfg_system_t *sys)
95 | {
96 | uint16_t ctr = pwm_from_set(cfg->vset, &sys->vout_pwm);
97 | uart_write_str("PWM VOLTAGE ");
98 | uart_write_int(ctr);
99 | uart_write_str("\r\n");
100 |
101 | TIM2_CCR1H = ctr >> 8;
102 | TIM2_CCR1L = ctr & 0xFF;
103 | TIM2_CR1 |= 0x01; // Enable timer
104 | }
105 |
106 | inline void control_current(cfg_output_t *cfg, cfg_system_t *sys)
107 | {
108 | uint16_t ctr = pwm_from_set(cfg->cset, &sys->cout_pwm);
109 | uart_write_str("PWM CURRENT ");
110 | uart_write_int(ctr);
111 | uart_write_str("\r\n");
112 |
113 | TIM1_CCR1H = ctr >> 8;
114 | TIM1_CCR1L = ctr & 0xFF;
115 | TIM1_CR1 |= 0x01; // Enable timer
116 | }
117 |
118 | void output_commit(cfg_output_t *cfg, cfg_system_t *sys, uint8_t state_constant_current)
119 | {
120 | // Startup and shutdown orders need to be in reverse order
121 | if (sys->output) {
122 | control_voltage(cfg, sys);
123 | control_current(cfg, sys);
124 |
125 | // We turned on the PWMs above already
126 | PB_ODR &= ~(1<<4);
127 | output_check_state(sys, state_constant_current);
128 | } else {
129 | // Set Output Enable OFF
130 | PB_ODR |= (1<<4);
131 |
132 | // Turn off PWM for Iout
133 | TIM1_CCR1H = 0;
134 | TIM1_CCR1L = 0;
135 | TIM1_CR1 &= 0xFE; // Disable timer
136 |
137 | // Turn off PWM for Vout
138 | TIM2_CCR1H = 0;
139 | TIM2_CCR1L = 0;
140 | TIM2_CR1 &= 0xFE; // Disable timer
141 |
142 | // Turn off CV/CC led
143 | cvcc_led_off();
144 | }
145 | }
146 |
147 | void output_check_state(cfg_system_t *sys, uint8_t state_constant_current)
148 | {
149 | if (sys->output) {
150 | if (state_constant_current)
151 | cvcc_led_cc();
152 | else
153 | cvcc_led_cv();
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/stm8/PROTOCOL.md:
--------------------------------------------------------------------------------
1 | # Serial Protocol
2 |
3 | This is a description of the serial protocol for this alternative firmware.
4 |
5 | ## Configuration
6 |
7 | The serial works at 9600 8N1, the low speed is intended to allow MCU to handle
8 | the flow without interfering too much with the rest of the work.
9 |
10 | ## Startup
11 |
12 | The controller will send a welcome message "B3603 alternative firmware vX.XX"
13 |
14 | ## Commands
15 |
16 | All commands are line-feed or carriage-return terminated, if the input buffer
17 | is filled with no LF or CR character the entire line is dumped and a message is
18 | sent on the output to indicate this failure.
19 |
20 | ### Model Query
21 |
22 | * Send: "MODEL"
23 | * Receive: "MODEL: B3603"
24 |
25 | This is just the model information, it is fixed for this firmware at this time
26 | as it only runs on a single device. There is however another device that seems
27 | to use the same controller board and then the model returned may be different.
28 |
29 | ### Version Query
30 |
31 | * Send: "VERSION"
32 | * Receive: "VERSION: X.XX"
33 |
34 | ### System Configuration Query
35 |
36 | * Send: "SYSTEM"
37 | * Receive: "SYSTEM:\r\nMODEL: \r\nVERSION: \r\nNAME: \r\nONSTARTUP: \r\nAUTOCOMMIT: \r\n"
38 |
39 | Get the system information: model, version, name, auto-on on startup and auto commit.
40 |
41 | ### Commit configuration
42 |
43 | * Send: "COMMIT"
44 | * Receive: "COMMIT: DONE\r\n"
45 |
46 | If auto commit is off this command will change the operating parameters according to the changes done since the last commit.
47 | If auto commit is on, this command is not going to change anything.
48 |
49 | ### Auto-commit Set
50 |
51 | * Send: "AUTOCOMMIT "
52 | * Receive: "AUTOMMIT: YES" or "AUTOCOMMIT: NO"
53 |
54 | Set the auto commit setting.
55 |
56 | ### Name Set
57 |
58 | * Send: "SNAME"
59 | * Receive: "SNAME: "
60 |
61 | Set the name to what the user gave. The size is limited to 16 characters and
62 | they must be printable characters.
63 |
64 | ### Calibration Values
65 |
66 | * Send: "CALIBRATION"
67 | * Receive: detailed on calibration, mostly useful to debug and comparison of units
68 |
69 | ### Voltage Capabilities Query
70 |
71 | * Send: "VLIST"
72 | * Receive: "VLIST: 1.0000/12.0000/0.0001"
73 |
74 | Returns minimum voltage, maximum voltage and step size.
75 |
76 | ### Current Capabilities Query
77 |
78 | * Send: "CLIST"
79 | * Receive: "CLIST: 0.001/3.000/0.001"
80 |
81 | Returns minimum current, maximum current and step size.
82 |
83 | ### Output Enable/Disable
84 |
85 | * Send: "OUTPUT 0" or "OUTPUT 1"
86 | * Receive: "OUTPUT: DISABLED" or "OUTPUT: ENABLED"
87 |
88 | OUTPUT0 disables the output and OUTPUT1 enables the output.
89 |
90 | ### Voltage Set
91 |
92 | * Send: "VOLTAGE X.XXXX"
93 | * Receive: "VOLTAGE: SET X.XXXX"
94 |
95 | Set the maximum voltage level.
96 |
97 | ### Current Set
98 |
99 | * Send: "CURRENT X.XXXX"
100 | * Receive: "CURRENT: SET X.XXXX"
101 |
102 | Set the maximum current level.
103 |
104 | ### Default at startup
105 |
106 | * Send: "DEFAULT 0" or "DEFAULT 1"
107 | * Receive: "DEFAULT: DISABLED" or "DEFAULT: ENABLED"
108 |
109 | Set the default for the output at startup, either enabled or disabled.
110 |
111 | Default disabled is better for safety, default enabled is useful when the unit
112 | powers an always on device and needs to always work without a manual
113 | intervention when the power comes back after a power outage.
114 |
115 | ### Over voltage protection
116 |
117 | * Send: "VSHUTDOWN X.XXXX" or "VSHUTDOWN 0"
118 | * Receive: "VSHUTDOWN: X.XXXX" or "VSHUTDOWN: DISABLED"
119 |
120 | When a VSHUTDOWN is set and reached the unit will turn off the output to avoid
121 | an over-voltage situation. This would be used in a constant current situation
122 | by setting the shutdown voltage lower than the max controlled voltage and let
123 | the microcontroller shutdown the entire output if the limit is reached.
124 |
125 | ### Over current protection
126 |
127 | * Send: "CSHUTDOWN 1" or "CSHUTDOWN 0"
128 | * Receive: "CSHUTDOWN: ENABLED" or "CSHUTDOWN: DISABLED"
129 |
130 | When a CSHUTDOWN is set and reached the unit will shutdown, current overload is
131 | considered when we reach the maximum current and the voltage drops by 10%
132 | already to handle the current control, at that point it is assumed the load is
133 | in short and the output is shutdown.
134 |
135 | ### Query configuration
136 |
137 | * Send: "CONFIG"
138 | * Receive: "CONFIG:\r\nOUTPUT: