├── 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: \r\nVOLTAGE SET: \r\nCURRENT SET: \r\nVOLTAGE SHUTDOWN: \r\nCURRENT SHUTDOWN: \r\n" 139 | 140 | Report all the config variables: 141 | 142 | * Output -- Output enabled "ON" or disabled "OFF" 143 | * Voutmax -- Voltage output maximum 144 | * Ioutmax -- Current output max as set 145 | * Vshutdown -- Voltage set for shutdown, or "DISABLED" for feature disabled 146 | * Cshutdown -- Current shutdown enabled "ON" or disabled "OFF" 147 | 148 | ### Status Report 149 | 150 | * Send: "STATUS" 151 | * Receive: "STATUS:\r\nOUTPUT: \r\nVOLTAGE IN: \r\nVOLTAGE OUT: \r\nVOLTAGE OUT: \r\nCONSTANT: \r\n" 152 | 153 | Reports all state variables: 154 | 155 | * Output -- Output enabled "ON" or disabled "OFF" 156 | * Vin -- Voltage Input to the unit 157 | * Vout -- Actual voltage output 158 | * Iout -- Actual current output 159 | * CCCV -- "CURRENT" if we are in constant current, "VOLTAGE" if we are in constant voltage 160 | 161 | ## Missing features 162 | 163 | * Calibration 164 | * Lock keys 165 | * Save settings to EEPROM, also load them at startup 166 | * Watchdog, can we output something on the serial? 167 | * Internal notification logic, monitor the output values and notify immediately 168 | on non-trivial change (i.e. apply hysteresis so minutiae errors are not 169 | noisy) 170 | -------------------------------------------------------------------------------- /stm8/uart.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 "uart.h" 20 | #include "fixedpoint.h" 21 | #include "stm8s.h" 22 | 23 | uint8_t uart_write_buf[255]; 24 | uint8_t uart_write_start; 25 | uint8_t uart_write_len; 26 | 27 | uint8_t uart_read_buf[64]; 28 | uint8_t uart_read_len; 29 | uint8_t read_newline; 30 | 31 | void uart_init() 32 | { 33 | USART1_CR1 = 0; // 8 bits, no parity 34 | USART1_CR2 = 0; 35 | USART1_CR3 = 0; 36 | 37 | USART1_BRR2 = 0x1; 38 | USART1_BRR1 = 0x1A; // 38400 baud, order important between BRRs, BRR1 must be last 39 | 40 | USART1_CR2 = USART_CR2_TEN | USART_CR2_REN; // Allow TX & RX 41 | 42 | uart_write_len = 0; 43 | uart_write_start = 0; 44 | uart_read_len = 0; 45 | read_newline = 0; 46 | } 47 | 48 | inline uint8_t uart_write_ready(void) 49 | { 50 | return (USART1_SR & USART_SR_TXE); 51 | } 52 | 53 | void uart_write_ch(const char ch) 54 | { 55 | if (uart_write_len < sizeof(uart_write_buf)) 56 | uart_write_buf[uart_write_len++] = ch; 57 | } 58 | 59 | void uart_write_str(const char *str) 60 | { 61 | uint8_t i; 62 | 63 | // Move the buffer to the start 64 | if (uart_write_start > 0) { 65 | for (i = 0; i < uart_write_len; i++) { 66 | uart_write_buf[i] = uart_write_buf[i+uart_write_start]; 67 | } 68 | uart_write_start = 0; 69 | } 70 | 71 | for(i = 0; str[i] != 0 && uart_write_len < sizeof(uart_write_buf); i++) { 72 | uart_write_buf[uart_write_len] = str[i]; 73 | uart_write_len++; 74 | } 75 | } 76 | 77 | uint8_t digits_buf[12]; 78 | static uint8_t int_to_digits(uint16_t val) 79 | { 80 | uint8_t i; 81 | uint8_t num_digits = 0; 82 | 83 | digits_buf[0] = '0'; 84 | 85 | for (i = 0; i < 6 && val != 0; i++) { 86 | uint8_t digit = val % 10; 87 | digits_buf[i] = '0' + digit; 88 | val /= 10; 89 | if (digit) // We only really want to know about non-zero digits 90 | num_digits = i; 91 | } 92 | 93 | return num_digits + 1; 94 | } 95 | 96 | void uart_write_int(uint16_t val) 97 | { 98 | int8_t i; 99 | uint8_t highest_nonzero; 100 | 101 | highest_nonzero = int_to_digits(val); 102 | 103 | for (i = highest_nonzero-1; i >= 0; i--) { 104 | uart_write_ch(digits_buf[i]); 105 | } 106 | } 107 | 108 | static uint8_t int32_to_digits(uint32_t val) 109 | { 110 | uint8_t i; 111 | uint8_t num_digits = 0; 112 | 113 | digits_buf[0] = '0'; 114 | 115 | for (i = 0; i < 12 && val != 0; i++) { 116 | uint8_t digit = val % 10; 117 | digits_buf[i] = '0' + digit; 118 | val /= 10; 119 | if (digit) // We only really want to know about non-zero digits 120 | num_digits = i; 121 | } 122 | 123 | return num_digits + 1; 124 | } 125 | 126 | void uart_write_int32(uint32_t val) 127 | { 128 | int8_t i; 129 | uint8_t highest_nonzero; 130 | 131 | highest_nonzero = int32_to_digits(val); 132 | 133 | for (i = highest_nonzero-1; i >= 0; i--) { 134 | uart_write_ch(digits_buf[i]); 135 | } 136 | } 137 | 138 | void uart_write_milliamp(uint16_t val) 139 | { 140 | int8_t i; 141 | uint8_t highest_nonzero; 142 | 143 | highest_nonzero = int_to_digits(val); 144 | 145 | for (i = highest_nonzero-1; i >= 0; i--) { 146 | if (i == 2) 147 | uart_write_ch('.'); 148 | uart_write_ch(digits_buf[i]); 149 | } 150 | } 151 | 152 | void uart_write_millivolt(uint16_t val) 153 | { 154 | int8_t i; 155 | uint8_t highest_nonzero; 156 | 157 | highest_nonzero = int_to_digits(val); 158 | 159 | for (i = highest_nonzero-1; i >= 0; i--) { 160 | if (i == 2) 161 | uart_write_ch('.'); 162 | uart_write_ch(digits_buf[i]); 163 | } 164 | } 165 | 166 | void uart_write_fixed_point(uint32_t val) 167 | { 168 | uint32_t tmp; 169 | 170 | // Print the integer part 171 | tmp = val >> FIXED_SHIFT; 172 | uart_write_int(tmp); 173 | uart_write_ch('.'); 174 | 175 | // Remove the integer part 176 | tmp = val & FIXED_FRACTION_MASK; 177 | 178 | // Take three decimal digits from the fraction part 179 | tmp = fixed_round(tmp*10000); 180 | 181 | // Pad with zeros if the number is too small 182 | if (tmp < 1000) 183 | uart_write_ch('0'); 184 | if (tmp < 100) 185 | uart_write_ch('0'); 186 | if (tmp < 10) 187 | uart_write_ch('0'); 188 | 189 | // Write the remaining fractional part 190 | uart_write_int32(tmp); 191 | } 192 | 193 | void uart_write_from_buf(void) 194 | { 195 | USART1_DR = uart_write_buf[uart_write_start]; 196 | uart_write_start++; 197 | uart_write_len--; 198 | 199 | if (uart_write_len == 0) 200 | uart_write_start = 0; 201 | } 202 | 203 | inline uint8_t uart_read_ch(void) 204 | { 205 | return USART1_DR; 206 | } 207 | 208 | void uart_read_to_buf(void) 209 | { 210 | // Don't read if we are writing 211 | uint8_t ch = uart_read_ch(); 212 | 213 | if (ch >= 'a' && ch <= 'z') 214 | ch = ch - 'a' + 'A'; // Convert letters to uppercase 215 | 216 | uart_read_buf[uart_read_len] = ch; 217 | uart_read_len++; 218 | 219 | if (ch == '\r' || ch == '\n') 220 | read_newline = 1; 221 | 222 | // Empty the read buf if we are overfilling and there is no full command in there 223 | if (uart_read_len == sizeof(uart_read_buf) && !read_newline) { 224 | uart_read_len = 0; 225 | uart_write_str("READ OVERFLOW\r\n"); 226 | } 227 | } 228 | 229 | void uart_drive(void) 230 | { 231 | uint8_t sr = USART1_SR; 232 | 233 | if (sr & USART_SR_RXNE) { 234 | uart_read_to_buf(); 235 | } 236 | if ((sr & USART_SR_TXE) && uart_write_len) { 237 | uart_write_from_buf(); 238 | } 239 | } 240 | 241 | void uart_flush_writes(void) 242 | { 243 | while (uart_write_len > 0) 244 | uart_drive(); 245 | } 246 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # B3603 2 | 3 | This project is about reverse engineering the B3603 control board and figuring 4 | out how it works, then it should be possible to create an alternative firmware. 5 | Either by driving it with another board on the same control points or by 6 | replacing the original firmware with one of my own. 7 | 8 | **Current state**: Working, it is functioning and serially controllable. 9 | 10 | Components needed: 11 | * [B3603](http://www.banggood.com/B3603-Precision-CNC-DC-DC-Digital-Buck-Module-Constant-Voltage-Current-p-946751.html?p=PA11121233669201502E) -- The unit being reprogrammed 12 | * [CP2102](http://www.banggood.com/Wholesale-USB-To-TTL-or-COM-Converter-Module-buildin-in-CP2102-New-p-27989.html?p=PA11121233669201502E) -- A usb-to-serial TTL-level 13 | * [STLink V2](http://www.aliexpress.com/item/FREE-SHIPPING-ST-Link-V2-stlink-mini-STM8STM32-STLINK-simulator-download-programming-With-Cover/1766455290.html) -- programmer for the STM8S microcontroller 14 | 15 | ## Schematics 16 | 17 | These were done by flex, the discussion can be seen in the EEVBlog forum (link at the bottom). 18 | 19 | [B3603 Board Schematics in PDF (top and bottom)](docs/B3603_BoardSchematics.pdf) 20 | 21 | Bottom board schematics: 22 | 23 | ![B3603 Bottom Board Schematics](docs/B3603_BottomBoardSchematics.png) 24 | 25 | Top board schematics: 26 | 27 | ![B3603 Top Board Schematics](docs/B3603_TopBoardSchematics.png) 28 | 29 | ## Regulator Board (bottom) 30 | 31 | ![Bottom Board Side 1](docs/BottomBoardSide1.jpg) 32 | 33 | ![Bottom Board Side 2](docs/BottomBoardSide2.jpg) 34 | 35 | ## Control Board (top) 36 | 37 | ![Top Board Side 1](docs/TopBoardSide1.jpg) 38 | 39 | ![Top Board Side 2](docs/TopBoardSide2.jpg) 40 | 41 | 42 | ### MCU 43 | 44 | The MCU is an [STM8S003F3](http://www.st.com/web/catalog/mmc/FM141/SC1244/SS1010/LN2/PF251792). It is the TSSOP-20 package. 45 | 46 | ### Pinouts 47 | 48 | Lets name the different pinout components, left and right are as seen looking at the top board with the 7-segment display up: 49 | 50 | * MCU 51 | * Left connector -- 8 pins left side 52 | * Right connector -- 8 pins right side 53 | * Serial connector -- 4 pins at left most side 54 | * SWIM connector -- 4 pins at the bottom, just left of the buttons 55 | * 74HC595 #1 -- The one closest to the MCU 56 | * 74HC595 #2 -- The one furthest from the MCU 57 | 58 | #### Pinout from MCU 59 | 60 | ![STM8S003F3 TSSOP20 pins](docs/STM8S003F3 pinout.png) 61 | 62 | | MCU pin | MCU Function | Board Connector | Board Connector Pin | Board Connector Name 63 | | ------- | -------------|-----------------|---------------------|----- 64 | | Pin 1 | UART1\_CK/TIM2\_CH1/BEEP/(HS) PD4 | 74HC595 | Pin 3 | DS 65 | | Pin 2 | UART1\_TX | Serial connector | Pin 2 | TX 66 | | Pin 3 | UART1\_RX | Serial connector | Pin 4 | RX 67 | | Pin 4 | NRST | SWIM | Pin 1 | SWIM NRST 68 | | Pin 5 | OSCIN/PA1 | 74HC595 | Pin 11 | SHCP 69 | | Pin 6 | OSCOUT/PA2 | 74HC595 | Pin 12 | STCP 70 | | Pin 7 | Vss (GND) | | | 71 | | Pin 8 | Vcap | | | 72 | | Pin 9 | Vdd | | | 73 | | Pin 10 | SPI\_NSS / TIM2\_CH3 / PA3 (HS) | CV/CC leds | | CV/CC leds 74 | | Pin 11 | PB5 (T) / I2C\_SDA / TIM1\_BKIN | Left connector | Pin 7 | CV/CC status 75 | | Pin 12 | PB4 (T) / I2C\_SCL / ADC\_ETR | Left connector | Pin 6 | Enable Output + Red (ON) led 76 | | Pin 13 | PC3 (HS) / TIM1\_CH3 [TLI] [TIM1_CH1N]| Left Connector | Pin 8 | Not connected 77 | | Pin 14 | PC4 (HS) / TIM1\_CH4 / CLK\_CCO / AIN2 / TIM1\_CH2N | Left connector | Pin 1 | Iout sense 16\*(0.01V + Iout\*0.05) 78 | | Pin 15 | PC5 (HS) / SPI\_SCK / TIM2\_CH1 | Left connector | Pin 5 | Vout set 79 | | Pin 16 | PC6 (HS) / SPI\_MOSI / TIM1\_CH1 | Left connector | Pin 4 | Iout set 80 | | Pin 17 | PC7 (HS) / SPI\_MISO / TIM1\_CH2 | Button | | Buttons 81 | | Pin 18 | PD1 (HS) / SWIM | SWIM | Pin 3 | SWIM & Buttons 82 | | Pin 19 | PD2 (HS) / AIN3 / TIM2\_CH3 | Left connector | Pin 2 | Vout sense 83 | | Pin 20 | PD3 (HS) / AIN4 / TIM2\_CH2 / ADC\_ETR | Left connector | Pin 3 | Vin sense (Vin/16) 84 | 85 | 86 | The buttons are connected in a strange setup where all four are on two pins. 87 | 88 | The CV/CC leds are in serial with a lead between them throuh a 10K resistor to pin PA3, by changing the pin between Output HIGH, Output LOW and Input it is possible to make one of them on or both off. 89 | 90 | #### Bottom Board Interface 91 | 92 | The below was decoded by [bal00](http://www.reddit.com/r/arduino/comments/2so02f/can_anyone_recommend_a_cheap_cheerful_bench_power/cnrjdxo). 93 | 94 | ![Control pinouts](docs/control_pinouts.png) 95 | 96 | Right side: 97 | 98 | * Top four (1-4) pins are GND 99 | * Next two (5-6) are Vcc +5V (seems wrong) 100 | * 7 is connected to MCU UART RX 101 | * 8 is connected to MCU UART TX 102 | 103 | Left side (Top to bottom): 104 | 105 | * Pin 1: Iout sense, 970mV/A + 140mV 106 | * Pin 2: Vout sense, 72mV/V + 42mV 107 | * Pin 3: Vin sense, 62mV/V 108 | * Pin 4: Iout control, 970mV/A + 140mV (PWM controlled, off when output off) 109 | * Pin 5: Vout control, 72mV/V + 42mV (PWM controlled, off when output off) 110 | * Pin 6: Enable control, 0V = output on, 5V = output off (Digitally controlled) 111 | * Pin 7: CC/CV sense, CV = 0.47V, CC = 2.5V 112 | * Pin 8: Connected to MCU pin 13 (PC3), unknown function 113 | 114 | #### Pinouts of 74HC595 chips 115 | 116 | There are two 74HC595 TSSOP16, these control the 4 digit 7 segment display, and possibly the leds as well. The 7 segment display has 12 pins and is controlled constantly to create a persistence-of-vision effect. 117 | 118 | ![74HC595 pinout](docs/74HC595_TSSOP16.png) 119 | 120 | ## Links 121 | 122 | * [Manufacturer product page](http://www.mhinstek.com/product/html/?106.html) (Chinese) ([English translation](https://translate.google.com/translate?sl=auto&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=http%3A%2F%2Fwww.mhinstek.com%2Fproduct%2Fhtml%2F%3F106.html&edit-text=)) 123 | * [EEVBlog forum discussion](http://www.eevblog.com/forum/reviews/b3603-dcdc-buck-converter-mini-review-and-how-the-set-key-could-be-fatal/) 124 | 125 | Components needed: 126 | * [B3603](http://www.banggood.com/B3603-Precision-CNC-DC-DC-Digital-Buck-Module-Constant-Voltage-Current-p-946751.html?p=PA11121233669201502E) -- The unit being reprogrammed 127 | * [CP2102](http://www.banggood.com/Wholesale-USB-To-TTL-or-COM-Converter-Module-buildin-in-CP2102-New-p-27989.html?p=PA11121233669201502E) -- A usb-to-serial TTL-level 128 | * [STLink V2](http://www.aliexpress.com/item/FREE-SHIPPING-ST-Link-V2-stlink-mini-STM8STM32-STLINK-simulator-download-programming-With-Cover/1766455290.html) -- programmer for the STM8S microcontroller 129 | 130 | -------------------------------------------------------------------------------- /stm8/calibrate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import serial 4 | import sys 5 | import time 6 | import csv 7 | import os 8 | import math 9 | 10 | def calc_average(data): 11 | return reduce(lambda x,y: x+y, data) / len(data) 12 | 13 | def calc_stddev(data, avg): 14 | tmp1 = map(lambda x: (x-avg)*(x-avg), data) 15 | tmp2 = calc_average(tmp1) 16 | return math.sqrt(tmp2) 17 | 18 | class B3603(object): 19 | def __init__(self, portname): 20 | self.portname = portname 21 | self.debug = False 22 | 23 | def open(self): 24 | self.s = serial.Serial(self.portname, baudrate=38400, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=0.2) 25 | if self.s.isOpen(): 26 | self.clear_input() 27 | s = self.model() 28 | print 'OPEN "%s"' % s 29 | if s == 'MODEL: B3603': 30 | return True 31 | else: 32 | print 'Couldnt read the right model out of the serial port, got "%s", expected to see "MODEL: B3603"' % s 33 | else: 34 | return False 35 | 36 | def close(self): 37 | self.s.close() 38 | 39 | def ser_write(self, data): 40 | if self.debug: 41 | print 'DEBUG OUT:', data 42 | for d in data: 43 | self.s.write(d) 44 | 45 | def clear_input(self): 46 | # Clear previous buffer 47 | while self.s.read() != '': 48 | pass 49 | 50 | def command(self, cmd): 51 | self.ser_write("%s\n" % cmd) 52 | data = '' 53 | while 1: 54 | a = self.s.read() 55 | if a == '': 56 | break 57 | else: 58 | data += a 59 | lines = [line.strip() for line in data.split('\r')] 60 | if self.debug: 61 | for line in lines: 62 | print 'DEBUG IN', line 63 | return lines 64 | 65 | def model(self): 66 | return self.command('MODEL')[0] 67 | 68 | def status(self): 69 | lines = self.command("STATUS") 70 | output = 'UNKNOWN' 71 | vin = 0 72 | vout = 0 73 | cout = 0 74 | constant = 'UNKNOWN' 75 | 76 | for line in lines: 77 | part = line.split(':') 78 | if part[0] == 'OUTPUT': 79 | output = part[1].strip() 80 | elif part[0] == 'VOLTAGE IN': 81 | vin = float(part[1].strip()) 82 | elif part[0] == 'VOLTAGE OUT': 83 | vout = float(part[1].strip()) 84 | elif part[0] == 'CURRENT OUT': 85 | cout = float(part[1].strip()) 86 | elif part[0] == 'CONSTANT': 87 | constant = part[1].strip() 88 | 89 | return dict(output=output, vin=vin, vout=vout, cout=cout, constant=constant) 90 | 91 | def rstatus(self): 92 | lines = self.command("RSTATUS") 93 | output = 'UNKNOWN' 94 | vin = 0 95 | vout = 0 96 | cout = 0 97 | vin_calc = 0 98 | vout_calc = 0 99 | cout_calc = 0 100 | constant = 'UNKNOWN' 101 | 102 | for line in lines: 103 | part = line.split(':') 104 | if part[0] == 'OUTPUT': 105 | output = part[1].strip() 106 | elif part[0] == 'VOLTAGE IN': 107 | vin_calc = float(part[1].strip()) 108 | elif part[0] == 'VOLTAGE OUT': 109 | vout_calc = float(part[1].strip()) 110 | elif part[0] == 'CURRENT OUT': 111 | cout_calc = float(part[1].strip()) 112 | elif part[0] == 'VOLTAGE IN ADC': 113 | vin = float(part[1].strip()) 114 | elif part[0] == 'VOLTAGE OUT ADC': 115 | vout = float(part[1].strip()) 116 | elif part[0] == 'CURRENT OUT ADC': 117 | cout = float(part[1].strip()) 118 | elif part[0] == 'CONSTANT': 119 | constant = part[1].strip() 120 | 121 | return dict(output=output, vin_adc=vin, vout_adc=vout, cout_adc=cout, constant=constant, vin_calc=vin_calc, vout_calc=vout_calc, cout_calc=cout_calc) 122 | 123 | 124 | def output_on(self): 125 | return self.command("OUTPUT 1") 126 | 127 | def output_off(self): 128 | return self.command("OUTPUT 0") 129 | 130 | def voltage(self, v): 131 | lines = self.command("VOLTAGE %.2f" % v) 132 | pwm_vout = None 133 | pwm_cout = None 134 | for line in lines: 135 | word = line.split(' ') 136 | if word[0] != 'PWM' and word[0] != 'aWM': continue 137 | if word[1] == 'VOLTAGE': pwm_vout = float(word[2]) 138 | if word[1] == 'CURRENT': pwm_cout = float(word[2]) 139 | return (pwm_vout, pwm_cout) 140 | 141 | def current(self, c): 142 | return self.command("CURRENT %.3f" % c) 143 | 144 | class Multimeter(object): 145 | def __init__(self, portname, model): 146 | self.portname = portname 147 | self.model = model 148 | 149 | def open(self): 150 | return self._sample() != None 151 | 152 | def _sample(self): 153 | p = os.popen('sigrok-cli -d %s:conn=%s --samples 1' % (self.model, self.portname)) 154 | s = p.read() 155 | p.close() 156 | return float(s.split(' ')[1]) 157 | 158 | def sample1(self, count): 159 | count = int(count) 160 | if count < 1: 161 | raise Exception("Invalid count value, must be above 0") 162 | if count == 1: 163 | return self._sample() 164 | 165 | data = [] 166 | for i in xrange(count): 167 | data.append(self._sample()) 168 | if data[-1] == None: 169 | return None 170 | 171 | avg = calc_average(data) 172 | stddev = calc_stddev(data, avg) 173 | if stddev > 0.1: 174 | print 'Multimeter samples vary too much, stddev=%f, data:' % stddev, data 175 | return None 176 | return avg 177 | 178 | def sample3(self, count): 179 | for i in range(3): 180 | s = self.sample1(count) 181 | if s != None: 182 | return s 183 | print 'Failed to read stable value, trying again, maybe' 184 | time.sleep(1) 185 | return None 186 | 187 | def lse(xdata, ydata): 188 | assert(len(xdata) == len(ydata)) 189 | sum_xy = 0 190 | sum_x = 0 191 | sum_y = 0 192 | sum_x2 = 0 193 | n = len(xdata) 194 | for i in xrange(n): 195 | x_i = xdata[i] 196 | y_i = ydata[i] 197 | sum_xy += x_i*y_i 198 | sum_x += x_i 199 | sum_y += y_i 200 | sum_x2 += x_i*x_i 201 | 202 | alpha = (n * sum_xy - sum_x*sum_y) / (n * sum_x2 - sum_x*sum_x) 203 | beta = (sum_y - alpha * sum_x) / n 204 | 205 | return (alpha, beta) 206 | 207 | def auto_calibration(): 208 | psu = B3603(sys.argv[2]) 209 | if not psu.open(): 210 | print 'Failed to open serial port to B3603 on serial %s' % sys.argv[2] 211 | return 212 | 213 | dmm = Multimeter(sys.argv[3], sys.argv[4]) 214 | if not dmm.open(): 215 | print 'Failed to open serial port to multimeter on serial %s model %s' % (sys.argv[3], sys.argv[4]) 216 | psu.close() 217 | return 218 | 219 | vin = psu.status()['vin'] 220 | NUM_STEPS = 20 221 | MIN_VOLTAGE = 1.0 222 | MAX_VOLTAGE = vin - 1.0 223 | STEP_SIZE_INT = int(100 * (MAX_VOLTAGE - MIN_VOLTAGE) / NUM_STEPS) 224 | STEP_SIZE = STEP_SIZE_INT / 100.0 225 | print 'PSU Input voltage is %s, will use %d steps between %s and %s' % (vin, NUM_STEPS, MIN_VOLTAGE, MAX_VOLTAGE) 226 | 227 | if STEP_SIZE < 0.01: 228 | print 'Step size is below 0.1, cannot test' 229 | return 230 | 231 | psu.output_on() 232 | psu.current(1.0) 233 | psu.voltage(MIN_VOLTAGE) 234 | 235 | pwm_data = [] 236 | adc_data = [] 237 | vout_data = [] 238 | valid = True 239 | 240 | for step in xrange(NUM_STEPS): 241 | volt = MIN_VOLTAGE + step * STEP_SIZE 242 | print 'Setting voltage to', volt 243 | (pwm_vout, pwm_cout) = psu.voltage(volt) 244 | # Wait 1 second for things to stabilize 245 | time.sleep(1) 246 | vout = dmm.sample3(3) # Use three samples 247 | if vout == None: 248 | print 'Failed to get vout' 249 | valid = False 250 | break 251 | if vout < 0.1: 252 | print 'Vout is too low (%s), something broke, try to reset the B3603 to defaults with RESTORE command first' % vout 253 | valid = False 254 | break 255 | if vin - vout < 0.5: 256 | print 'Vout is %s and Vin is %s, this means that pwm calibration is saturated and the test will be meaningless' % (vout, vin) 257 | valid = False 258 | break 259 | rstatus = psu.rstatus() 260 | adc_vout = rstatus['vout_adc'] 261 | vout_calc = rstatus['vout_calc'] 262 | 263 | pwm_data.append(pwm_vout) 264 | adc_data.append(adc_vout) 265 | vout_data.append(int(vout*1000)) 266 | print 'Step %d Set voltage %f Read voltage %f PWM %s ADC %s (%s)' % (step, volt, vout, pwm_vout, adc_vout, vout_calc) 267 | 268 | print psu.output_off() 269 | 270 | if not valid: 271 | print 'Test is invalid, calibration cancelled' 272 | return 273 | 274 | print 'ADC' 275 | val = lse(adc_data, vout_data) 276 | adc_a = int(val[0]*65536) 277 | adc_b_tmp = val[1] 278 | if adc_b_tmp < 0: 279 | adc_b_tmp = -adc_b_tmp 280 | else: 281 | print 'Expected ADC_B to be negative... for some reason it\'ts not' 282 | adc_b_tmp = 0 283 | adc_b = int(adc_b_tmp*65536) 284 | print val, adc_a, adc_b 285 | print psu.command('CALVOUTADCA %d' % adc_a) 286 | print psu.command('CALVOUTADCB %d' % adc_b) 287 | print 288 | print 'PWM' 289 | val = lse(vout_data, pwm_data) 290 | pwm_a = int(val[0]*65536) 291 | pwm_b = int(val[1]*65536) 292 | print val, pwm_a, pwm_b 293 | print psu.command('CALVOUTPWMA %d' % pwm_a) 294 | print psu.command('CALVOUTPWMB %d' % pwm_b) 295 | 296 | psu.close() 297 | 298 | def manual_calibration(): 299 | print 'Not implemented' 300 | 301 | def usage(): 302 | print '%s -a ' % sys.argv[0] 303 | print 304 | print 'or:' 305 | print 306 | print '%s -m ' % sys.argv[0] 307 | 308 | def main(): 309 | if len(sys.argv) < 2: 310 | return usage() 311 | 312 | if sys.argv[1] == '-a': 313 | if len(sys.argv) != 5: 314 | return usage() 315 | else: 316 | auto_calibration() 317 | 318 | if sys.argv[1] == '-m': 319 | if len(sys.argv) != 2: 320 | return usage() 321 | else: 322 | manual_calibration() 323 | 324 | if __name__ == '__main__': 325 | main() 326 | -------------------------------------------------------------------------------- /stm8/stm8s.h: -------------------------------------------------------------------------------- 1 | /* This file is merely a collection of facts and as such I don't claim any copyright on it. */ 2 | 3 | /* GPIO */ 4 | #define PA_ODR *(unsigned char*)0x5000 5 | #define PA_IDR *(unsigned char*)0x5001 6 | #define PA_DDR *(unsigned char*)0x5002 7 | #define PA_CR1 *(unsigned char*)0x5003 8 | #define PA_CR2 *(unsigned char*)0x5004 9 | 10 | #define PB_ODR *(unsigned char*)0x5005 11 | #define PB_IDR *(unsigned char*)0x5006 12 | #define PB_DDR *(unsigned char*)0x5007 13 | #define PB_CR1 *(unsigned char*)0x5008 14 | #define PB_CR2 *(unsigned char*)0x5009 15 | 16 | #define PC_ODR *(unsigned char*)0x500A 17 | #define PC_IDR *(unsigned char*)0x500B 18 | #define PC_DDR *(unsigned char*)0x500C 19 | #define PC_CR1 *(unsigned char*)0x500D 20 | #define PC_CR2 *(unsigned char*)0x500E 21 | 22 | #define PD_ODR *(unsigned char*)0x500F 23 | #define PD_IDR *(unsigned char*)0x5010 24 | #define PD_DDR *(unsigned char*)0x5011 25 | #define PD_CR1 *(unsigned char*)0x5012 26 | #define PD_CR2 *(unsigned char*)0x5013 27 | 28 | #define PE_ODR *(unsigned char*)0x5014 29 | #define PE_IDR *(unsigned char*)0x5015 30 | #define PE_DDR *(unsigned char*)0x5016 31 | #define PE_CR1 *(unsigned char*)0x5017 32 | #define PE_CR2 *(unsigned char*)0x5018 33 | 34 | #define PF_ODR *(unsigned char*)0x5019 35 | #define PF_IDR *(unsigned char*)0x501A 36 | #define PF_DDR *(unsigned char*)0x501B 37 | #define PF_CR1 *(unsigned char*)0x501C 38 | #define PF_CR2 *(unsigned char*)0x501D 39 | 40 | /* CLOCK */ 41 | #define CLK_ICKR *(unsigned char*)0x50C0 42 | #define CLK_ECKR *(unsigned char*)0x50C1 43 | #define CLK_CMSR *(unsigned char*)0x50C3 44 | #define CLK_SWR *(unsigned char*)0x50C4 45 | #define CLK_SWCR *(unsigned char*)0x50C5 46 | #define CLK_CKDIVR *(unsigned char*)0x50C6 47 | #define CLK_PCKENR1 *(unsigned char*)0x50C7 48 | #define CLK_CSSR *(unsigned char*)0x50C8 49 | #define CLK_CCOR *(unsigned char*)0x50C9 50 | #define CLK_PCKENR2 *(unsigned char*)0x50CA 51 | #define CLK_HSITRIMR *(unsigned char*)0x50CC 52 | #define CLK_SWIMCCR *(unsigned char*)0x50CD 53 | 54 | /* ------------------- USART ------------------- */ 55 | #define USART1_SR *(unsigned char*)0x5230 56 | #define USART1_DR *(unsigned char*)0x5231 57 | #define USART1_BRR1 *(unsigned char*)0x5232 58 | #define USART1_BRR2 *(unsigned char*)0x5233 59 | #define USART1_CR1 *(unsigned char*)0x5234 60 | #define USART1_CR2 *(unsigned char*)0x5235 61 | #define USART1_CR3 *(unsigned char*)0x5236 62 | #define USART1_CR4 *(unsigned char*)0x5237 63 | #define USART1_CR5 *(unsigned char*)0x5238 64 | #define USART1_GTR *(unsigned char*)0x5239 65 | #define USART1_PSCR *(unsigned char*)0x523A 66 | 67 | /* USART_CR1 bits */ 68 | #define USART_CR1_R8 (1 << 7) 69 | #define USART_CR1_T8 (1 << 6) 70 | #define USART_CR1_UARTD (1 << 5) 71 | #define USART_CR1_M (1 << 4) 72 | #define USART_CR1_WAKE (1 << 3) 73 | #define USART_CR1_PCEN (1 << 2) 74 | #define USART_CR1_PS (1 << 1) 75 | #define USART_CR1_PIEN (1 << 0) 76 | 77 | /* USART_CR2 bits */ 78 | #define USART_CR2_TIEN (1 << 7) 79 | #define USART_CR2_TCIEN (1 << 6) 80 | #define USART_CR2_RIEN (1 << 5) 81 | #define USART_CR2_ILIEN (1 << 4) 82 | #define USART_CR2_TEN (1 << 3) 83 | #define USART_CR2_REN (1 << 2) 84 | #define USART_CR2_RWU (1 << 1) 85 | #define USART_CR2_SBK (1 << 0) 86 | 87 | /* USART_CR3 bits */ 88 | #define USART_CR3_LINEN (1 << 6) 89 | #define USART_CR3_STOP2 (1 << 5) 90 | #define USART_CR3_STOP1 (1 << 4) 91 | #define USART_CR3_CLKEN (1 << 3) 92 | #define USART_CR3_CPOL (1 << 2) 93 | #define USART_CR3_CPHA (1 << 1) 94 | #define USART_CR3_LBCL (1 << 0) 95 | 96 | /* USART_SR bits */ 97 | #define USART_SR_TXE (1 << 7) 98 | #define USART_SR_TC (1 << 6) 99 | #define USART_SR_RXNE (1 << 5) 100 | #define USART_SR_IDLE (1 << 4) 101 | #define USART_SR_OR (1 << 3) 102 | #define USART_SR_NF (1 << 2) 103 | #define USART_SR_FE (1 << 1) 104 | #define USART_SR_PE (1 << 0) 105 | 106 | 107 | /* ------------------- TIMERS ------------------- */ 108 | #define TIM1_CR1 *(unsigned char*)0x5250 109 | #define TIM1_CR2 *(unsigned char*)0x5251 110 | #define TIM1_SMCR *(unsigned char*)0x5252 111 | #define TIM1_ETR *(unsigned char*)0x5253 112 | #define TIM1_IER *(unsigned char*)0x5254 113 | #define TIM1_SR1 *(unsigned char*)0x5255 114 | #define TIM1_SR2 *(unsigned char*)0x5256 115 | #define TIM1_EGR *(unsigned char*)0x5257 116 | #define TIM1_CCMR1 *(unsigned char*)0x5258 117 | #define TIM1_CCMR2 *(unsigned char*)0x5259 118 | #define TIM1_CCMR3 *(unsigned char*)0x525A 119 | #define TIM1_CCMR4 *(unsigned char*)0x525B 120 | #define TIM1_CCER1 *(unsigned char*)0x525C 121 | #define TIM1_CCER2 *(unsigned char*)0x525D 122 | #define TIM1_CNTRH *(unsigned char*)0x525E 123 | #define TIM1_CNTRL *(unsigned char*)0x525F 124 | #define TIM1_PSCRH *(unsigned char*)0x5260 125 | #define TIM1_PSCRL *(unsigned char*)0x5261 126 | #define TIM1_ARRH *(unsigned char*)0x5262 127 | #define TIM1_ARRL *(unsigned char*)0x5263 128 | #define TIM1_RCR *(unsigned char*)0x5264 129 | #define TIM1_CCR1H *(unsigned char*)0x5265 130 | #define TIM1_CCR1L *(unsigned char*)0x5266 131 | #define TIM1_CCR2H *(unsigned char*)0x5267 132 | #define TIM1_CCR2L *(unsigned char*)0x5268 133 | #define TIM1_CCR3H *(unsigned char*)0x5269 134 | #define TIM1_CCR3L *(unsigned char*)0x526A 135 | #define TIM1_CCR4H *(unsigned char*)0x526B 136 | #define TIM1_CCR4L *(unsigned char*)0x526C 137 | #define TIM1_BKR *(unsigned char*)0x526D 138 | #define TIM1_DTR *(unsigned char*)0x526E 139 | #define TIM1_OISR *(unsigned char*)0x526F 140 | 141 | #define TIM2_CR1 *(unsigned char*)0x5300 142 | #define TIM2_IER *(unsigned char*)0x5303 143 | #define TIM2_SR1 *(unsigned char*)0x5304 144 | #define TIM2_SR2 *(unsigned char*)0x5305 145 | #define TIM2_EGR *(unsigned char*)0x5306 146 | #define TIM2_CCMR1 *(unsigned char*)0x5307 147 | #define TIM2_CCMR2 *(unsigned char*)0x5308 148 | #define TIM2_CCMR3 *(unsigned char*)0x5309 149 | #define TIM2_CCER1 *(unsigned char*)0x530A 150 | #define TIM2_CCER2 *(unsigned char*)0x530B 151 | #define TIM2_CNTRH *(unsigned char*)0x530C 152 | #define TIM2_CNTRL *(unsigned char*)0x530D 153 | #define TIM2_PSCR *(unsigned char*)0x530E 154 | #define TIM2_ARRH *(unsigned char*)0x530F 155 | #define TIM2_ARRL *(unsigned char*)0x5310 156 | #define TIM2_CCR1H *(unsigned char*)0x5311 157 | #define TIM2_CCR1L *(unsigned char*)0x5312 158 | #define TIM2_CCR2H *(unsigned char*)0x5313 159 | #define TIM2_CCR2L *(unsigned char*)0x5314 160 | #define TIM2_CCR3H *(unsigned char*)0x5315 161 | #define TIM2_CCR3L *(unsigned char*)0x5316 162 | 163 | /* TIM_IER bits */ 164 | #define TIM_IER_BIE (1 << 7) 165 | #define TIM_IER_TIE (1 << 6) 166 | #define TIM_IER_COMIE (1 << 5) 167 | #define TIM_IER_CC4IE (1 << 4) 168 | #define TIM_IER_CC3IE (1 << 3) 169 | #define TIM_IER_CC2IE (1 << 2) 170 | #define TIM_IER_CC1IE (1 << 1) 171 | #define TIM_IER_UIE (1 << 0) 172 | 173 | /* TIM_CR1 bits */ 174 | #define TIM_CR1_APRE (1 << 7) 175 | #define TIM_CR1_CMSH (1 << 6) 176 | #define TIM_CR1_CMSL (1 << 5) 177 | #define TIM_CR1_DIR (1 << 4) 178 | #define TIM_CR1_OPM (1 << 3) 179 | #define TIM_CR1_URS (1 << 2) 180 | #define TIM_CR1_UDIS (1 << 1) 181 | #define TIM_CR1_CEN (1 << 0) 182 | 183 | /* TIM_SR1 bits */ 184 | #define TIM_SR1_BIF (1 << 7) 185 | #define TIM_SR1_TIF (1 << 6) 186 | #define TIM_SR1_COMIF (1 << 5) 187 | #define TIM_SR1_CC4IF (1 << 4) 188 | #define TIM_SR1_CC3IF (1 << 3) 189 | #define TIM_SR1_CC2IF (1 << 2) 190 | #define TIM_SR1_CC1IF (1 << 1) 191 | #define TIM_SR1_UIF (1 << 0) 192 | 193 | 194 | /* ------------------- ADC1 ------------------- */ 195 | #define ADC1_DB0H *(unsigned char*)0x53E0 196 | #define ADC1_DB0L *(unsigned char*)0x53E1 197 | #define ADC1_DB1H *(unsigned char*)0x53E2 198 | #define ADC1_DB1L *(unsigned char*)0x53E3 199 | #define ADC1_DB2H *(unsigned char*)0x53E4 200 | #define ADC1_DB2L *(unsigned char*)0x53E5 201 | #define ADC1_DB3H *(unsigned char*)0x53E6 202 | #define ADC1_DB3L *(unsigned char*)0x53E7 203 | #define ADC1_DB4H *(unsigned char*)0x53E8 204 | #define ADC1_DB4L *(unsigned char*)0x53E9 205 | #define ADC1_DB5H *(unsigned char*)0x53EA 206 | #define ADC1_DB5L *(unsigned char*)0x53EB 207 | #define ADC1_DB6H *(unsigned char*)0x53EC 208 | #define ADC1_DB6L *(unsigned char*)0x53ED 209 | #define ADC1_DB7H *(unsigned char*)0x53EE 210 | #define ADC1_DB7L *(unsigned char*)0x53EF 211 | #define ADC1_DB8H *(unsigned char*)0x53F0 212 | #define ADC1_DB8L *(unsigned char*)0x53F1 213 | #define ADC1_DB9H *(unsigned char*)0x53F2 214 | #define ADC1_DB9L *(unsigned char*)0x53F3 215 | 216 | #define ADC1_CSR *(unsigned char*)0x5400 217 | #define ADC1_CR1 *(unsigned char*)0x5401 218 | #define ADC1_CR2 *(unsigned char*)0x5402 219 | #define ADC1_CR3 *(unsigned char*)0x5403 220 | #define ADC1_DRH *(unsigned char*)0x5404 221 | #define ADC1_DRL *(unsigned char*)0x5405 222 | #define ADC1_TDRH *(unsigned char*)0x5406 223 | #define ADC1_TDRL *(unsigned char*)0x5407 224 | #define ADC1_HTRH *(unsigned char*)0x5408 225 | #define ADC1_HTRL *(unsigned char*)0x5409 226 | #define ADC1_LTRH *(unsigned char*)0x540A 227 | #define ADC1_LTRL *(unsigned char*)0x540B 228 | #define ADC1_AWSRH *(unsigned char*)0x540C 229 | #define ADC1_AWSRL *(unsigned char*)0x540D 230 | #define ADC1_AWCRH *(unsigned char*)0x540E 231 | #define ADC1_AWCRL *(unsigned char*)0x540F 232 | 233 | /* ---------------- CPU/SWIM registers ----------------*/ 234 | #define CFG_GCR *(unsigned char*)0x7F60 235 | #define SWIM_CSR *(unsigned char*)0x7F80 236 | #define RST_SR *(unsigned char*)0x50B3 237 | 238 | /* IWDG */ 239 | #define IWDG_KR *(unsigned char *)0x50E0 240 | #define IWDG_PR *(unsigned char *)0x50E1 241 | #define IWDG_RLR *(unsigned char *)0x50E2 242 | 243 | /* Option bytes */ 244 | #define OPT0 *(unsigned char *)0x4800 245 | #define OPT1 *(unsigned char *)0x4801 246 | #define NOPT1 *(unsigned char *)0x4802 247 | #define OPT2 *(unsigned char *)0x4803 248 | #define NOPT2 *(unsigned char *)0x4804 249 | #define OPT3 *(unsigned char *)0x4805 250 | #define NOPT3 *(unsigned char *)0x4806 251 | #define OPT4 *(unsigned char *)0x4807 252 | #define NOPT4 *(unsigned char *)0x4808 253 | #define OPT5 *(unsigned char *)0x4809 254 | #define NOPT5 *(unsigned char *)0x480A 255 | 256 | /* Flash */ 257 | #define FLASH_CR1 *(unsigned char *)0x505A 258 | #define FLASH_CR2 *(unsigned char *)0x505B 259 | #define FLASH_NCR2 *(unsigned char *)0x505C 260 | #define FLASH_FPR *(unsigned char *)0x505D 261 | #define FLASH_NFPR *(unsigned char *)0x505E 262 | #define FLASH_IAPSR *(unsigned char *)0x505F 263 | #define FLASH_PUKR *(unsigned char *)0x5062 264 | #define FLASH_DUKR *(unsigned char *)0x5064 265 | 266 | #define FLASH_CR1_HALT (1<<3) 267 | #define FLASH_CR1_AHALT (1<<2) 268 | #define FLASH_CR1_IE (1<<1) 269 | #define FLASH_CR1_FIX (1<<0) 270 | 271 | #define FLASH_CR2_OPT (1<<7) 272 | #define FLASH_CR2_WPRG (1<<6) 273 | #define FLASH_CR2_ERASE (1<<5) 274 | #define FLASH_CR2_FPRG (1<<4) 275 | #define FLASH_CR2_PRG (1<<0) 276 | 277 | #define FLASH_NCR2_NOPT (1<<7) 278 | #define FLASH_NCR2_NWPRG (1<<6) 279 | #define FLASH_NCR2_NERASE (1<<5) 280 | #define FLASH_NCR2_NFPRG (1<<4) 281 | #define FLASH_NCR2_NPRG (1<<0) 282 | 283 | #define FLASH_IAPSR_HVOFF (1<<6) 284 | #define FLASH_IAPSR_DUL (1<<3) 285 | #define FLASH_IAPSR_EOP (1<<2) 286 | #define FLASH_IAPSR_PUL (1<<1) 287 | #define FLASH_IAPSR_WR_PG_DIS (1<<0) 288 | -------------------------------------------------------------------------------- /stm8/main.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 | #define FW_VERSION "1.0.1" 20 | #define MODEL "B3603" 21 | 22 | #include "stm8s.h" 23 | #include 24 | #include 25 | #include 26 | 27 | #include "display.h" 28 | #include "fixedpoint.h" 29 | #include "uart.h" 30 | #include "eeprom.h" 31 | #include "outputs.h" 32 | #include "config.h" 33 | #include "parse.h" 34 | #include "adc.h" 35 | 36 | #define CAP_VMIN 10 // 10mV 37 | #define CAP_VMAX 35000 // 35 V 38 | #define CAP_VSTEP 10 // 10mV 39 | 40 | #define CAP_CMIN 1 // 1 mA 41 | #define CAP_CMAX 3000 // 3 A 42 | #define CAP_CSTEP 1 // 1 mA 43 | 44 | cfg_system_t cfg_system; 45 | cfg_output_t cfg_output; 46 | state_t state; 47 | 48 | inline iwatchdog_init(void) 49 | { 50 | IWDG_KR = 0xCC; // Enable IWDG 51 | // The default values give us about 15msec between pings 52 | } 53 | 54 | inline iwatchdog_tick(void) 55 | { 56 | IWDG_KR = 0xAA; // Reset the counter 57 | } 58 | 59 | void commit_output() 60 | { 61 | output_commit(&cfg_output, &cfg_system, state.constant_current); 62 | } 63 | 64 | void set_name(uint8_t *name) 65 | { 66 | uint8_t idx; 67 | 68 | for (idx = 0; name[idx] != 0; idx++) { 69 | if (!isprint(name[idx])) 70 | name[idx] = '.'; // Eliminate non-printable chars 71 | } 72 | 73 | memcpy(cfg_system.name, name, sizeof(cfg_system.name)); 74 | cfg_system.name[sizeof(cfg_system.name)-1] = 0; 75 | 76 | uart_write_str("SNAME: "); 77 | uart_write_str(cfg_system.name); 78 | uart_write_str("\r\n"); 79 | } 80 | 81 | void autocommit(void) 82 | { 83 | if (cfg_system.autocommit) { 84 | commit_output(); 85 | } else { 86 | uart_write_str("AUTOCOMMIT OFF: CHANGE PENDING ON COMMIT\r\n"); 87 | } 88 | } 89 | 90 | void set_output(uint8_t *s) 91 | { 92 | if (s[1] != 0) { 93 | uart_write_str("OUTPUT takes either 0 for OFF or 1 for ON, received: \""); 94 | uart_write_str(s); 95 | uart_write_str("\"\r\n"); 96 | return; 97 | } 98 | 99 | if (s[0] == '0') { 100 | cfg_system.output = 0; 101 | uart_write_str("OUTPUT: OFF\r\n"); 102 | } else if (s[0] == '1') { 103 | cfg_system.output = 1; 104 | uart_write_str("OUTPUT: ON\r\n"); 105 | } else { 106 | uart_write_str("OUTPUT takes either 0 for OFF or 1 for ON, received: \""); 107 | uart_write_str(s); 108 | uart_write_str("\"\r\n"); 109 | } 110 | 111 | autocommit(); 112 | } 113 | 114 | void set_voltage(uint8_t *s) 115 | { 116 | fixed_t val; 117 | 118 | val = parse_millinum(s); 119 | if (val == 0xFFFF) 120 | return; 121 | 122 | if (val > CAP_VMAX) { 123 | uart_write_str("VOLTAGE VALUE TOO HIGH\r\n"); 124 | return; 125 | } 126 | if (val < CAP_VMIN) { 127 | uart_write_str("VOLTAGE VALUE TOO LOW\r\n"); 128 | return; 129 | } 130 | 131 | uart_write_str("VOLTAGE: SET "); 132 | uart_write_millivolt(val); 133 | uart_write_str("\r\n"); 134 | cfg_output.vset = val; 135 | 136 | autocommit(); 137 | } 138 | 139 | void set_current(uint8_t *s) 140 | { 141 | fixed_t val; 142 | 143 | val = parse_millinum(s); 144 | if (val == 0xFFFF) 145 | return; 146 | 147 | if (val > CAP_CMAX) { 148 | uart_write_str("CURRENT VALUE TOO HIGH\r\n"); 149 | return; 150 | } 151 | if (val < CAP_CMIN) { 152 | uart_write_str("CURRENT VALUE TOO LOW\r\n"); 153 | return; 154 | } 155 | 156 | uart_write_str("CURRENT: SET "); 157 | uart_write_milliamp(val); 158 | uart_write_str("\r\n"); 159 | cfg_output.cset = val; 160 | 161 | autocommit(); 162 | } 163 | 164 | void set_autocommit(uint8_t *s) 165 | { 166 | if (strcmp(s, "1") == 0 || strcmp(s, "YES") == 0) { 167 | cfg_system.autocommit = 1; 168 | uart_write_str("AUTOCOMMIT: YES\r\n"); 169 | } else if (strcmp(s, "0") == 0 || strcmp(s, "NO") == 0) { 170 | cfg_system.autocommit = 0; 171 | uart_write_str("AUTOCOMMIT: NO\r\n"); 172 | } else { 173 | uart_write_str("UNKNOWN AUTOCOMMIT ARG: "); 174 | uart_write_str(s); 175 | uart_write_str("\r\n"); 176 | } 177 | } 178 | 179 | void write_str(const char *prefix, const char *val) 180 | { 181 | uart_write_str(prefix); 182 | uart_write_str(val); 183 | uart_write_str("\r\n"); 184 | } 185 | 186 | void write_onoff(const char *prefix, uint8_t on) 187 | { 188 | write_str(prefix, on ? "ON" : "OFF"); 189 | } 190 | 191 | void write_millivolt(const char *prefix, uint16_t mv) 192 | { 193 | uart_write_str(prefix); 194 | uart_write_millivolt(mv); 195 | uart_write_str("\r\n"); 196 | } 197 | 198 | void write_milliamp(const char *prefix, uint16_t ma) 199 | { 200 | uart_write_str(prefix); 201 | uart_write_milliamp(ma); 202 | uart_write_str("\r\n"); 203 | } 204 | 205 | void write_int(const char *prefix, uint16_t val) 206 | { 207 | uart_write_str(prefix); 208 | uart_write_int(val); 209 | uart_write_str("\r\n"); 210 | } 211 | 212 | uint32_t _parse_uint(uint8_t *s) 213 | { 214 | uint32_t val = 0; 215 | 216 | for (; *s; s++) { 217 | uint8_t ch = *s; 218 | if (ch >= '0' && ch <= '9') { 219 | val = val*10 + (ch-'0'); 220 | } else { 221 | return 0xFFFFFFFF; 222 | } 223 | } 224 | 225 | return val; 226 | } 227 | 228 | void parse_uint(const char *name, uint32_t *pval, uint8_t *s) 229 | { 230 | uint32_t val = _parse_uint(s); 231 | if (val == 0xFFFFFFFF) { 232 | uart_write_str("FAILED TO PARSE "); 233 | uart_write_str(s); 234 | uart_write_str(" FOR "); 235 | uart_write_str(name); 236 | } else { 237 | *pval = val; 238 | uart_write_str("CALIBRATION SET "); 239 | uart_write_str(name); 240 | } 241 | uart_write_str("\r\n"); 242 | } 243 | 244 | void process_input() 245 | { 246 | // Eliminate the CR/LF character 247 | uart_read_buf[uart_read_len-1] = 0; 248 | 249 | if (strcmp(uart_read_buf, "MODEL") == 0) { 250 | uart_write_str("MODEL: " MODEL "\r\n"); 251 | } else if (strcmp(uart_read_buf, "VERSION") == 0) { 252 | uart_write_str("VERSION: " FW_VERSION "\r\n"); 253 | } else if (strcmp(uart_read_buf, "SYSTEM") == 0) { 254 | uart_write_str("MODEL: " MODEL "\r\n" "VERSION: " FW_VERSION "\r\n"); 255 | 256 | write_str("NAME: ", cfg_system.name); 257 | write_onoff("ONSTARTUP: ", cfg_system.default_on); 258 | write_onoff("AUTOCOMMIT: ", cfg_system.autocommit); 259 | } else if (strcmp(uart_read_buf, "CALIBRATION") == 0) { 260 | uart_write_str("CALIBRATE VIN ADC: "); 261 | uart_write_fixed_point(cfg_system.vin_adc.a); 262 | uart_write_ch('/'); 263 | uart_write_fixed_point(cfg_system.vin_adc.b); 264 | uart_write_str("\r\n"); 265 | uart_write_str("CALIBRATE VOUT ADC: "); 266 | uart_write_fixed_point(cfg_system.vout_adc.a); 267 | uart_write_ch('/'); 268 | uart_write_fixed_point(cfg_system.vout_adc.b); 269 | uart_write_str("\r\n"); 270 | uart_write_str("CALIBRATE COUT ADC: "); 271 | uart_write_fixed_point(cfg_system.cout_adc.a); 272 | uart_write_ch('/'); 273 | uart_write_fixed_point(cfg_system.cout_adc.b); 274 | uart_write_str("\r\n"); 275 | uart_write_str("CALIBRATE VOUT PWM: "); 276 | uart_write_fixed_point(cfg_system.vout_pwm.a); 277 | uart_write_ch('/'); 278 | uart_write_fixed_point(cfg_system.vout_pwm.b); 279 | uart_write_str("\r\n"); 280 | uart_write_str("CALIBRATE COUT PWM: "); 281 | uart_write_fixed_point(cfg_system.cout_pwm.a); 282 | uart_write_ch('/'); 283 | uart_write_fixed_point(cfg_system.cout_pwm.b); 284 | uart_write_str("\r\n"); 285 | } else if (strcmp(uart_read_buf, "RCALIBRATION") == 0) { 286 | uart_write_str("CALIBRATE VIN ADC: "); 287 | uart_write_int32(cfg_system.vin_adc.a); 288 | uart_write_ch('/'); 289 | uart_write_int32(cfg_system.vin_adc.b); 290 | uart_write_str("\r\n"); 291 | uart_write_str("CALIBRATE VOUT ADC: "); 292 | uart_write_int32(cfg_system.vout_adc.a); 293 | uart_write_ch('/'); 294 | uart_write_int32(cfg_system.vout_adc.b); 295 | uart_write_str("\r\n"); 296 | uart_write_str("CALIBRATE COUT ADC: "); 297 | uart_write_int32(cfg_system.cout_adc.a); 298 | uart_write_ch('/'); 299 | uart_write_int32(cfg_system.cout_adc.b); 300 | uart_write_str("\r\n"); 301 | uart_write_str("CALIBRATE VOUT PWM: "); 302 | uart_write_int32(cfg_system.vout_pwm.a); 303 | uart_write_ch('/'); 304 | uart_write_int32(cfg_system.vout_pwm.b); 305 | uart_write_str("\r\n"); 306 | uart_write_str("CALIBRATE COUT PWM: "); 307 | uart_write_int32(cfg_system.cout_pwm.a); 308 | uart_write_ch('/'); 309 | uart_write_int32(cfg_system.cout_pwm.b); 310 | uart_write_ch('\r'); 311 | } else if (strcmp(uart_read_buf, "LIMITS") == 0) { 312 | uart_write_str("LIMITS:\r\n"); 313 | write_millivolt("VMIN: ", CAP_VMIN); 314 | write_millivolt("VMAX: ", CAP_VMAX); 315 | write_millivolt("VSTEP: ", CAP_VSTEP); 316 | write_milliamp("CMIN: ", CAP_CMIN); 317 | write_milliamp("CMAX: ", CAP_CMAX); 318 | write_milliamp("CSTEP: ", CAP_CSTEP); 319 | } else if (strcmp(uart_read_buf, "CONFIG") == 0) { 320 | uart_write_str("CONFIG:\r\n"); 321 | write_onoff("OUTPUT: ", cfg_system.output); 322 | write_millivolt("VSET: ", cfg_output.vset); 323 | write_milliamp("CSET: ", cfg_output.cset); 324 | write_millivolt("VSHUTDOWN: ", cfg_output.vshutdown); 325 | write_millivolt("CSHUTDOWN: ", cfg_output.cshutdown); 326 | } else if (strcmp(uart_read_buf, "STATUS") == 0) { 327 | uart_write_str("STATUS:\r\n"); 328 | write_onoff("OUTPUT: ", cfg_system.output); 329 | write_millivolt("VIN: ", state.vin); 330 | write_millivolt("VOUT: ", state.vout); 331 | write_milliamp("COUT: ", state.cout); 332 | write_str("CONSTANT: ", state.constant_current ? "CURRENT" : "VOLTAGE"); 333 | } else if (strcmp(uart_read_buf, "RSTATUS") == 0) { 334 | uart_write_str("RSTATUS:\r\n"); 335 | write_onoff("OUTPUT: ", cfg_system.output); 336 | write_int("VIN ADC: ", state.vin_raw); 337 | write_millivolt("VIN: ", state.vin); 338 | write_int("VOUT ADC: ", state.vout_raw); 339 | write_millivolt("VOUT: ", state.vout); 340 | write_int("COUT ADC: ", state.cout_raw); 341 | write_milliamp("COUT: ", state.cout); 342 | write_str("CONSTANT: ", state.constant_current ? "CURRENT" : "VOLTAGE"); 343 | } else if (strcmp(uart_read_buf, "COMMIT") == 0) { 344 | commit_output(); 345 | } else if (strcmp(uart_read_buf, "SAVE") == 0) { 346 | config_save_system(&cfg_system); 347 | config_save_output(&cfg_output); 348 | uart_write_str("SAVED\r\n"); 349 | } else if (strcmp(uart_read_buf, "LOAD") == 0) { 350 | config_load_system(&cfg_system); 351 | config_load_output(&cfg_output); 352 | autocommit(); 353 | } else if (strcmp(uart_read_buf, "RESTORE") == 0) { 354 | config_default_system(&cfg_system); 355 | config_default_output(&cfg_output); 356 | autocommit(); 357 | #if DEBUG 358 | } else if (strcmp(uart_read_buf, "STUCK") == 0) { 359 | // Allows debugging of the IWDG feature 360 | uart_write_str("STUCK\r\n"); 361 | uart_write_flush(); 362 | while(1); // Induce watchdog reset 363 | #endif 364 | } else { 365 | // Process commands with arguments 366 | uint8_t idx; 367 | uint8_t space_found = 0; 368 | 369 | for (idx = 0; idx < uart_read_len; idx++) { 370 | if (uart_read_buf[idx] == ' ') { 371 | uart_read_buf[idx] = 0; 372 | space_found = 1; 373 | break; 374 | } 375 | } 376 | 377 | if (space_found) { 378 | if (strcmp(uart_read_buf, "SNAME") == 0) { 379 | set_name(uart_read_buf + idx + 1); 380 | } else if (strcmp(uart_read_buf, "OUTPUT") == 0) { 381 | set_output(uart_read_buf + idx + 1); 382 | } else if (strcmp(uart_read_buf, "VOLTAGE") == 0) { 383 | set_voltage(uart_read_buf + idx + 1); 384 | } else if (strcmp(uart_read_buf, "CURRENT") == 0) { 385 | set_current(uart_read_buf + idx + 1); 386 | } else if (strcmp(uart_read_buf, "AUTOCOMMIT") == 0) { 387 | set_autocommit(uart_read_buf + idx + 1); 388 | /* } else if (strcmp(uart_read_buf, "CALVIN1") == 0) { 389 | calibrate_vin(1, parse_millinum(uart_read_buf+idx+1), state.vin_raw, &cfg_system.vin_adc); 390 | } else if (strcmp(uart_read_buf, "CALVIN2") == 0) { 391 | calibrate_vin(2, parse_millinum(uart_read_buf+idx+1), state.vin_raw, &cfg_system.vin_adc); 392 | } else if (strcmp(uart_read_buf, "CALVOUT1") == 0) { 393 | calibrate_vout(1, parse_millinum(uart_read_buf+idx+1), state.vout_raw, &cfg_system.vout_adc, &cfg_system.vout_pwm); 394 | } else if (strcmp(uart_read_buf, "CALVOUT2") == 0) { 395 | calibrate_vout(2, parse_millinum(uart_read_buf+idx+1), state.vout_raw, &cfg_system.vout_adc, &cfg_system.vout_pwm); 396 | } else if (strcmp(uart_read_buf, "CALCOUT1") == 0) { 397 | calibrate_cout(1, parse_millinum(uart_read_buf+idx+1), state.cout_raw, &cfg_system.cout_adc, &cfg_system.cout_pwm); 398 | } else if (strcmp(uart_read_buf, "CALCOUT2") == 0) { 399 | calibrate_cout(2, parse_millinum(uart_read_buf+idx+1), state.cout_raw, &cfg_system.cout_adc, &cfg_system.cout_pwm); */ 400 | } else if (strcmp(uart_read_buf, "CALVOUTADCA") == 0) { 401 | parse_uint("ADC VOUT A", &cfg_system.vout_adc.a, uart_read_buf+idx+1); 402 | } else if (strcmp(uart_read_buf, "CALVOUTADCB") == 0) { 403 | parse_uint("ADC VOUT B", &cfg_system.vout_adc.b, uart_read_buf+idx+1); 404 | } else if (strcmp(uart_read_buf, "CALVOUTPWMA") == 0) { 405 | parse_uint("PWM VOUT A", &cfg_system.vout_pwm.a, uart_read_buf+idx+1); 406 | } else if (strcmp(uart_read_buf, "CALVOUTPWMB") == 0) { 407 | parse_uint("PWM VOUT B", &cfg_system.vout_pwm.b, uart_read_buf+idx+1); 408 | } else if (strcmp(uart_read_buf, "CALCOUTADCA") == 0) { 409 | parse_uint("ADC COUT A", &cfg_system.cout_adc.a, uart_read_buf+idx+1); 410 | } else if (strcmp(uart_read_buf, "CALCOUTADCB") == 0) { 411 | parse_uint("ADC COUT B", &cfg_system.cout_adc.b, uart_read_buf+idx+1); 412 | } else if (strcmp(uart_read_buf, "CALCOUTPWMA") == 0) { 413 | parse_uint("PWM COUT A", &cfg_system.cout_pwm.a, uart_read_buf+idx+1); 414 | } else if (strcmp(uart_read_buf, "CALCOUTPWMB") == 0) { 415 | parse_uint("PWM COUT B", &cfg_system.cout_pwm.b, uart_read_buf+idx+1); 416 | } else { 417 | uart_write_str("UNKNOWN COMMAND!\r\n"); 418 | } 419 | } else { 420 | uart_write_str("UNKNOWN COMMAND\r\n"); 421 | } 422 | } 423 | uart_write_str("DONE\r\n"); 424 | 425 | uart_read_len = 0; 426 | read_newline = 0; 427 | } 428 | 429 | inline void clk_init() 430 | { 431 | CLK_CKDIVR = 0x00; // Set the frequency to 16 MHz 432 | } 433 | 434 | inline void pinout_init() 435 | { 436 | // PA1 is 74HC595 SHCP, output 437 | // PA2 is 74HC595 STCP, output 438 | // PA3 is CV/CC leds, output (& input to disable) 439 | PA_ODR = 0; 440 | PA_DDR = (1<<1) | (1<<2); 441 | PA_CR1 = (1<<1) | (1<<2) | (1<<3); 442 | PA_CR2 = (1<<1) | (1<<2) | (1<<3); 443 | 444 | // PB4 is Enable control, output 445 | // PB5 is CV/CC sense, input 446 | PB_ODR = (1<<4); // For safety we start with off-state 447 | PB_DDR = (1<<4); 448 | PB_CR1 = (1<<4); 449 | PB_CR2 = 0; 450 | 451 | // PC3 is unknown, input 452 | // PC4 is Iout sense, input adc, AIN2 453 | // PC5 is Vout control, output 454 | // PC6 is Iout control, output 455 | // PC7 is Button 1, input 456 | PC_ODR = 0; 457 | PC_DDR = (1<<5) || (1<<6); 458 | PC_CR1 = (1<<7); // For the button 459 | PC_CR2 = (1<<5) | (1<<6); 460 | 461 | // PD1 is Button 2, input 462 | // PD2 is Vout sense, input adc, AIN3 463 | // PD3 is Vin sense, input adc, AIN4 464 | // PD4 is 74HC595 DS, output 465 | PD_DDR = (1<<4); 466 | PD_CR1 = (1<<1) | (1<<4); // For the button 467 | PD_CR2 = (1<<4); 468 | } 469 | 470 | void config_load(void) 471 | { 472 | config_load_system(&cfg_system); 473 | config_load_output(&cfg_output); 474 | 475 | if (cfg_system.default_on) 476 | cfg_system.output = 1; 477 | else 478 | cfg_system.output = 0; 479 | 480 | state.pc3 = 1; 481 | } 482 | 483 | void read_state(void) 484 | { 485 | uint8_t tmp; 486 | 487 | tmp = (PC_IDR & (1<<3)) ? 1 : 0; 488 | if (state.pc3 != tmp) { 489 | uart_write_str("PC3 is now "); 490 | uart_write_ch('0' + tmp); 491 | uart_write_str("\r\n"); 492 | state.pc3 = tmp; 493 | } 494 | 495 | tmp = (PB_IDR & (1<<5)) ? 1 : 0; 496 | if (state.constant_current != tmp) { 497 | state.constant_current = tmp; 498 | output_check_state(&cfg_system, state.constant_current); 499 | } 500 | 501 | if (adc_ready()) { 502 | uint16_t val = adc_read(); 503 | uint8_t ch = adc_channel(); 504 | 505 | switch (ch) { 506 | case 2: 507 | state.cout_raw = val; 508 | // Calculation: val * cal_cout_a * 3.3 / 1024 - cal_cout_b 509 | state.cout = adc_to_volt(val, &cfg_system.cout_adc); 510 | ch = 3; 511 | break; 512 | case 3: 513 | state.vout_raw = val; 514 | // Calculation: val * cal_vout_a * 3.3 / 1024 - cal_vout_b 515 | state.vout = adc_to_volt(val, &cfg_system.vout_adc); 516 | ch = 4; 517 | break; 518 | case 4: 519 | state.vin_raw = val; 520 | // Calculation: val * cal_vin * 3.3 / 1024 521 | state.vin = adc_to_volt(val, &cfg_system.vin_adc); 522 | ch = 2; 523 | { 524 | uint8_t ch1; 525 | uint8_t ch2; 526 | uint8_t ch3; 527 | uint8_t ch4; 528 | 529 | ch1 = '0' + (val / 10000) % 10; 530 | ch2 = '0' + (val / 1000) % 10; 531 | ch3 = '0' + (val / 100) % 10; 532 | ch4 = '0' + (val / 10 ) % 10; 533 | 534 | display_show(ch1, 0, ch2, 1, ch3, 0, ch4, 0); 535 | } 536 | break; 537 | } 538 | 539 | adc_start(ch); 540 | } 541 | } 542 | 543 | void ensure_afr0_set(void) 544 | { 545 | if ((OPT2 & 1) == 0) { 546 | uart_flush_writes(); 547 | if (eeprom_set_afr0()) { 548 | uart_write_str("AFR0 set, reseting the unit\r\n"); 549 | uart_flush_writes(); 550 | iwatchdog_init(); 551 | while (1); // Force a reset in a few msec 552 | } 553 | else { 554 | uart_write_str("AFR0 not set and programming failed!\r\n"); 555 | } 556 | } 557 | } 558 | 559 | int main() 560 | { 561 | unsigned long i = 0; 562 | 563 | pinout_init(); 564 | clk_init(); 565 | uart_init(); 566 | pwm_init(); 567 | adc_init(); 568 | 569 | config_load(); 570 | 571 | uart_write_str("\r\n" MODEL " starting: Version " FW_VERSION "\r\n"); 572 | 573 | ensure_afr0_set(); 574 | 575 | iwatchdog_init(); 576 | adc_start(4); 577 | commit_output(); 578 | 579 | do { 580 | iwatchdog_tick(); 581 | read_state(); 582 | display_refresh(); 583 | uart_drive(); 584 | if (read_newline) { 585 | process_input(); 586 | } 587 | } while(1); 588 | } 589 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /stm8/COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------