├── CommunicationOverview.ods ├── GD32F130C8 Dokumentation ├── GD32F130.pdf ├── GD32F1x0_User_Manual.pdf └── TUEV-Report-AKKU.pdf ├── Hardware_Overview_small.png ├── HoverBoardGigaDevice ├── EventRecorderStub.scvd ├── Hoverboard.uvguix.Florian ├── Hoverboard.uvoptx ├── Hoverboard.uvprojx ├── Inc │ ├── bldc.h │ ├── comms.h │ ├── commsBluetooth.h │ ├── commsMasterSlave.h │ ├── commsSteering.h │ ├── config.h │ ├── defines.h │ ├── it.h │ ├── led.h │ └── setup.h ├── Listings │ ├── Hoverboard.map │ └── startup_gd32f1x0.lst ├── RTE │ ├── Device │ │ └── GD32F130C8 │ │ │ ├── gd32f1x0_adc.c │ │ │ ├── gd32f1x0_dbg.c │ │ │ ├── gd32f1x0_dma.c │ │ │ ├── gd32f1x0_fwdgt.c │ │ │ ├── gd32f1x0_gpio.c │ │ │ ├── gd32f1x0_i2c.c │ │ │ ├── gd32f1x0_misc.c │ │ │ ├── gd32f1x0_opa.c │ │ │ ├── gd32f1x0_pmu.c │ │ │ ├── gd32f1x0_rcu.c │ │ │ ├── gd32f1x0_syscfg.c │ │ │ ├── gd32f1x0_timer.c │ │ │ ├── gd32f1x0_usart.c │ │ │ ├── gd32f1x0_wwdgt.c │ │ │ ├── startup_gd32f1x0.s │ │ │ └── system_gd32f1x0.c │ └── _Target_1 │ │ └── RTE_Components.h └── Src │ ├── bldc.c │ ├── comms.c │ ├── commsBluetooth.c │ ├── commsMasterSlave.c │ ├── commsSteering.c │ ├── it.c │ ├── led.c │ ├── main.c │ └── setup.c ├── LICENSE ├── PPMDeviceArduino_V1.0 └── PPMDevice │ ├── PPMDevice.ino │ ├── RCReceiver.cpp │ ├── RCReceiver.h │ ├── SteeringSerial.cpp │ ├── SteeringSerial.h │ └── utils.h ├── README.md ├── Raumzeigerdiagramm.png └── Schematics ├── HoverBoard_CoolAndFun.pdf └── HoverBoard_CoolAndFun.sch /CommunicationOverview.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flo199213/Hoverboard-Firmware-Hack-Gen2/e138b221aed944478d12e15d81fb858f44f4a289/CommunicationOverview.ods -------------------------------------------------------------------------------- /GD32F130C8 Dokumentation/GD32F130.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flo199213/Hoverboard-Firmware-Hack-Gen2/e138b221aed944478d12e15d81fb858f44f4a289/GD32F130C8 Dokumentation/GD32F130.pdf -------------------------------------------------------------------------------- /GD32F130C8 Dokumentation/GD32F1x0_User_Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flo199213/Hoverboard-Firmware-Hack-Gen2/e138b221aed944478d12e15d81fb858f44f4a289/GD32F130C8 Dokumentation/GD32F1x0_User_Manual.pdf -------------------------------------------------------------------------------- /GD32F130C8 Dokumentation/TUEV-Report-AKKU.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flo199213/Hoverboard-Firmware-Hack-Gen2/e138b221aed944478d12e15d81fb858f44f4a289/GD32F130C8 Dokumentation/TUEV-Report-AKKU.pdf -------------------------------------------------------------------------------- /Hardware_Overview_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flo199213/Hoverboard-Firmware-Hack-Gen2/e138b221aed944478d12e15d81fb858f44f4a289/Hardware_Overview_small.png -------------------------------------------------------------------------------- /HoverBoardGigaDevice/EventRecorderStub.scvd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/bldc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef BLDC_H 32 | #define BLDC_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | //---------------------------------------------------------------------------- 38 | // Set motor enable 39 | //---------------------------------------------------------------------------- 40 | void SetEnable(FlagStatus setEnable); 41 | 42 | //---------------------------------------------------------------------------- 43 | // Set pwm -1000 to 1000 44 | //---------------------------------------------------------------------------- 45 | void SetPWM(int16_t setPwm); 46 | 47 | //---------------------------------------------------------------------------- 48 | // Calculation-Routine for BLDC => calculates with 16kHz 49 | //---------------------------------------------------------------------------- 50 | void CalculateBLDC(void); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/comms.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef COMMS_H 32 | #define COMMS_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | //---------------------------------------------------------------------------- 38 | // Send buffer via USART 39 | //---------------------------------------------------------------------------- 40 | void SendBuffer(uint32_t usart_periph, uint8_t buffer[], uint8_t length); 41 | 42 | //---------------------------------------------------------------------------- 43 | // Calculate CRC 44 | //---------------------------------------------------------------------------- 45 | uint16_t CalcCRC(uint8_t *ptr, int count); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/commsBluetooth.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef COMMSBLUETOOTH_H 32 | #define COMMSBLUETOOTH_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | // Only slave communicates over bluetooth 38 | #ifdef SLAVE 39 | 40 | //---------------------------------------------------------------------------- 41 | // Update USART bluetooth input 42 | //---------------------------------------------------------------------------- 43 | void UpdateUSARTBluetoothInput(void); 44 | 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/commsMasterSlave.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef COMMSMASTERSLAVE_H 32 | #define COMMSMASTERSLAVE_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | //---------------------------------------------------------------------------- 38 | // Update USART master slave input 39 | //---------------------------------------------------------------------------- 40 | void UpdateUSARTMasterSlaveInput(void); 41 | 42 | #ifdef MASTER 43 | //---------------------------------------------------------------------------- 44 | // Send slave frame via USART 45 | //---------------------------------------------------------------------------- 46 | void SendSlave(int16_t pwmSlave, FlagStatus enable, FlagStatus shutoff, FlagStatus chargeState, uint8_t identifier, int16_t value); 47 | #endif 48 | #ifdef SLAVE 49 | //---------------------------------------------------------------------------- 50 | // Send master frame via USART 51 | //---------------------------------------------------------------------------- 52 | void SendMaster(FlagStatus upperLEDMaster, FlagStatus lowerLEDMaster, FlagStatus mosfetOutMaster, FlagStatus beepsBackwards); 53 | 54 | //---------------------------------------------------------------------------- 55 | // Returns current value sent by master 56 | //---------------------------------------------------------------------------- 57 | int16_t GetCurrentDCMaster(void); 58 | 59 | //---------------------------------------------------------------------------- 60 | // Returns battery value sent by master 61 | //---------------------------------------------------------------------------- 62 | int16_t GetBatteryMaster(void); 63 | 64 | //---------------------------------------------------------------------------- 65 | // Returns realspeed value sent by master 66 | //---------------------------------------------------------------------------- 67 | int16_t GetRealSpeedMaster(void); 68 | 69 | //---------------------------------------------------------------------------- 70 | // Sets upper LED value which will be send to master 71 | //---------------------------------------------------------------------------- 72 | void SetUpperLEDMaster(FlagStatus value); 73 | 74 | //---------------------------------------------------------------------------- 75 | // Returns upper LED value sent by master 76 | //---------------------------------------------------------------------------- 77 | FlagStatus GetUpperLEDMaster(void); 78 | 79 | //---------------------------------------------------------------------------- 80 | // Sets lower LED value which will be send to master 81 | //---------------------------------------------------------------------------- 82 | void SetLowerLEDMaster(FlagStatus value); 83 | 84 | //---------------------------------------------------------------------------- 85 | // Returns lower LED value sent by master 86 | //---------------------------------------------------------------------------- 87 | FlagStatus GetLowerLEDMaster(void); 88 | 89 | //---------------------------------------------------------------------------- 90 | // Sets mosfetOut value which will be send to master 91 | //---------------------------------------------------------------------------- 92 | void SetMosfetOutMaster(FlagStatus value); 93 | 94 | //---------------------------------------------------------------------------- 95 | // Returns MosfetOut value sent by master 96 | //---------------------------------------------------------------------------- 97 | FlagStatus GetMosfetOutMaster(void); 98 | 99 | //---------------------------------------------------------------------------- 100 | // Sets beepsBackwards value which will be send to master 101 | //---------------------------------------------------------------------------- 102 | void SetBeepsBackwardsMaster(FlagStatus value); 103 | 104 | //---------------------------------------------------------------------------- 105 | // Returns beepsBackwardsMaster value sent by master 106 | //---------------------------------------------------------------------------- 107 | FlagStatus GetBeepsBackwardsMaster(void); 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/commsSteering.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef COMMSSTEERING_H 32 | #define COMMSSTEERING_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | // Only master communicates with steering device 38 | #ifdef MASTER 39 | //---------------------------------------------------------------------------- 40 | // Update USART steer input 41 | //---------------------------------------------------------------------------- 42 | void UpdateUSARTSteerInput(void); 43 | 44 | //---------------------------------------------------------------------------- 45 | // Send frame to steer device 46 | //---------------------------------------------------------------------------- 47 | void SendSteerDevice(void); 48 | #endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flo199213/Hoverboard-Firmware-Hack-Gen2/e138b221aed944478d12e15d81fb858f44f4a289/HoverBoardGigaDevice/Inc/config.h -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/defines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef DEFINES_H 32 | #define DEFINES_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | // LED defines 38 | #define LED_GREEN GPIO_PIN_15 39 | #define LED_GREEN_PORT GPIOA 40 | #define LED_ORANGE GPIO_PIN_12 41 | #define LED_ORANGE_PORT GPIOA 42 | #define LED_RED GPIO_PIN_3 43 | #define LED_RED_PORT GPIOB 44 | 45 | #define UPPER_LED_PIN GPIO_PIN_1 46 | #define UPPER_LED_PORT GPIOA 47 | #define LOWER_LED_PIN GPIO_PIN_0 48 | #define LOWER_LED_PORT GPIOA 49 | 50 | // Mosfet output 51 | #define MOSFET_OUT_PIN GPIO_PIN_13 52 | #define MOSFET_OUT_PORT GPIOC 53 | 54 | // Brushless Control DC (BLDC) defines 55 | // Channel G 56 | #define RCU_TIMER_BLDC RCU_TIMER0 57 | #define TIMER_BLDC TIMER0 58 | #define TIMER_BLDC_CHANNEL_G TIMER_CH_2 59 | #define TIMER_BLDC_GH_PIN GPIO_PIN_10 60 | #define TIMER_BLDC_GH_PORT GPIOA 61 | #define TIMER_BLDC_GL_PIN GPIO_PIN_15 62 | #define TIMER_BLDC_GL_PORT GPIOB 63 | // Channel B 64 | #define TIMER_BLDC_CHANNEL_B TIMER_CH_1 65 | #define TIMER_BLDC_BH_PIN GPIO_PIN_9 66 | #define TIMER_BLDC_BH_PORT GPIOA 67 | #define TIMER_BLDC_BL_PIN GPIO_PIN_14 68 | #define TIMER_BLDC_BL_PORT GPIOB 69 | // Channel Y 70 | #define TIMER_BLDC_CHANNEL_Y TIMER_CH_0 71 | #define TIMER_BLDC_YH_PIN GPIO_PIN_8 72 | #define TIMER_BLDC_YH_PORT GPIOA 73 | #define TIMER_BLDC_YL_PIN GPIO_PIN_13 74 | #define TIMER_BLDC_YL_PORT GPIOB 75 | 76 | // Timer BLDC short circuit emergency shutoff define 77 | #define TIMER_BLDC_EMERGENCY_SHUTDOWN_PIN GPIO_PIN_12 78 | #define TIMER_BLDC_EMERGENCY_SHUTDOWN_PORT GPIOB 79 | 80 | // Hall sensor defines 81 | #define HALL_A_PIN GPIO_PIN_11 82 | #define HALL_A_PORT GPIOB 83 | #define HALL_B_PIN GPIO_PIN_1 84 | #define HALL_B_PORT GPIOF 85 | #define HALL_C_PIN GPIO_PIN_14 86 | #define HALL_C_PORT GPIOC 87 | 88 | // Usart master slave defines 89 | #define USART_MASTERSLAVE USART1 90 | #define USART_MASTERSLAVE_TX_PIN GPIO_PIN_2 91 | #define USART_MASTERSLAVE_TX_PORT GPIOA 92 | #define USART_MASTERSLAVE_RX_PIN GPIO_PIN_3 93 | #define USART_MASTERSLAVE_RX_PORT GPIOA 94 | 95 | // ADC defines 96 | #define VBATT_PIN GPIO_PIN_4 97 | #define VBATT_PORT GPIOA 98 | #define VBATT_CHANNEL ADC_CHANNEL_4 99 | #define CURRENT_DC_PIN GPIO_PIN_6 100 | #define CURRENT_DC_PORT GPIOA 101 | #define CURRENT_DC_CHANNEL ADC_CHANNEL_6 102 | 103 | // Self hold defines 104 | #define SELF_HOLD_PIN GPIO_PIN_2 105 | #define SELF_HOLD_PORT GPIOB 106 | 107 | // Button defines 108 | #define BUTTON_PIN GPIO_PIN_15 109 | #define BUTTON_PORT GPIOC 110 | 111 | // Usart steer defines 112 | #define USART_STEER_COM USART0 113 | #define USART_STEER_COM_TX_PIN GPIO_PIN_6 114 | #define USART_STEER_COM_TX_PORT GPIOB 115 | #define USART_STEER_COM_RX_PIN GPIO_PIN_7 116 | #define USART_STEER_COM_RX_PORT GPIOB 117 | 118 | #ifdef MASTER 119 | // Buzzer defins 120 | #define BUZZER_PIN GPIO_PIN_10 121 | #define BUZZER_PORT GPIOB 122 | 123 | // Charge state defines 124 | #define CHARGE_STATE_PIN GPIO_PIN_0 125 | #define CHARGE_STATE_PORT GPIOF 126 | #endif 127 | 128 | // Debug pin defines 129 | #define DEBUG_PIN GPIO_PIN_4 130 | #define DEBUG_PORT GPIOB 131 | 132 | // ADC value conversion defines 133 | #define MOTOR_AMP_CONV_DC_AMP 0.201465201465 // 3,3V * 1/3 - 0,004Ohm * IL(ampere) = (ADC-Data/4095) *3,3V 134 | #define ADC_BATTERY_VOLT 0.024169921875 // V_Batt to V_BattMeasure = factor 30: ( (ADC-Data/4095) *3,3V *30 ) 135 | 136 | // Useful math function defines 137 | #define ABS(a) (((a) < 0.0) ? -(a) : (a)) 138 | #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) 139 | #define MAX(x, high) (((x) > (high)) ? (high) : (x)) 140 | #define MAP(x, xMin, xMax, yMin, yMax) ((x - xMin) * (yMax - yMin) / (xMax - xMin) + yMin) 141 | 142 | // ADC buffer struct 143 | typedef struct 144 | { 145 | uint16_t v_batt; 146 | uint16_t current_dc; 147 | } adc_buf_t; 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/it.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef IT_H 32 | #define IT_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | //---------------------------------------------------------------------------- 38 | // Resets the timeout to zero 39 | //---------------------------------------------------------------------------- 40 | void ResetTimeout(void); 41 | 42 | //---------------------------------------------------------------------------- 43 | // Returns number of milliseconds since system start 44 | //---------------------------------------------------------------------------- 45 | uint32_t millis( void ); 46 | 47 | //---------------------------------------------------------------------------- 48 | // Delays number of tick Systicks (happens every 10 ms) 49 | //---------------------------------------------------------------------------- 50 | void Delay (uint32_t dlyTicks); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/led.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef LED_H 32 | #define LED_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | // Only slave has LED mechanism 38 | #ifdef SLAVE 39 | 40 | // Modes for RGB-LED operation 41 | typedef enum 42 | { 43 | LED_OFF = 0, 44 | LED_HSB = 1, 45 | LED_HSB_BLINK = 2, 46 | LED_HSB_FADE = 3, 47 | LED_HSB_STROBE = 4 48 | } LED_PROGRAM; 49 | 50 | #define COUNT_PROGRAMS 6 // Count of LED programs!! 51 | 52 | //---------------------------------------------------------------------------- 53 | // Update RGB LED output with 16kHz 54 | //---------------------------------------------------------------------------- 55 | void CalculateLEDPWM(void); 56 | 57 | //---------------------------------------------------------------------------- 58 | // Update RGB LED program every 1ms 59 | //---------------------------------------------------------------------------- 60 | void CalculateLEDProgram(void); 61 | 62 | //---------------------------------------------------------------------------- 63 | // Sets/Gets LED program 64 | //---------------------------------------------------------------------------- 65 | void SetRGBProgram(LED_PROGRAM Program); 66 | LED_PROGRAM GetRGBProgram(void); 67 | 68 | //---------------------------------------------------------------------------- 69 | // Sets/Gets hue from 0-764 70 | //---------------------------------------------------------------------------- 71 | void SetHSBHue(uint16_t hue); 72 | uint16_t GetHSBHue(void); 73 | 74 | //---------------------------------------------------------------------------- 75 | // Sets/Gets saturation from 0-128 76 | //---------------------------------------------------------------------------- 77 | void SetHSBSaturation(uint8_t saturation); 78 | uint8_t GetHSBSaturation(void); 79 | 80 | //---------------------------------------------------------------------------- 81 | // Sets/Gets brightness from 0-63 82 | //---------------------------------------------------------------------------- 83 | void SetHSBBrightness(uint8_t brightnessVal); 84 | uint8_t GetHSBBrightness(void); 85 | 86 | 87 | //---------------------------------------------------------------------------- 88 | // Sets/Gets fading speed from 200-1000 89 | //---------------------------------------------------------------------------- 90 | void SetSpeedFading(uint16_t speed); 91 | uint16_t GetSpeedFading(void); 92 | 93 | //---------------------------------------------------------------------------- 94 | // Sets/Gets blink speed from 700-2400 95 | //---------------------------------------------------------------------------- 96 | void SetSpeedBlink(uint16_t speed); 97 | uint16_t GetSpeedBlink(void); 98 | 99 | //---------------------------------------------------------------------------- 100 | // Sets/Gets strobe speed from 0-1000 101 | //---------------------------------------------------------------------------- 102 | void SetSpeedStrobe(uint16_t speed); 103 | uint16_t GetSpeedStrobe(void); 104 | 105 | #endif 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Inc/setup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef SETUP_H 32 | #define SETUP_H 33 | 34 | #include "gd32f1x0.h" 35 | #include "../Inc/config.h" 36 | 37 | 38 | #define USART_MASTERSLAVE_RX_BUFFERSIZE 1 39 | #define USART_MASTERSLAVE_DATA_RX_ADDRESS ((uint32_t)0x40004424) 40 | 41 | #define USART_STEER_COM_RX_BUFFERSIZE 1 42 | #define USART_STEER_COM_DATA_RX_ADDRESS ((uint32_t)0x40013824) 43 | 44 | //---------------------------------------------------------------------------- 45 | // Initializes the interrupts 46 | //---------------------------------------------------------------------------- 47 | void Interrupt_init(void); 48 | 49 | //---------------------------------------------------------------------------- 50 | // Initializes the watchdog 51 | //---------------------------------------------------------------------------- 52 | ErrStatus Watchdog_init(void); 53 | 54 | //---------------------------------------------------------------------------- 55 | // Initializes the timeout timer 56 | //---------------------------------------------------------------------------- 57 | void TimeoutTimer_init(void); 58 | 59 | //---------------------------------------------------------------------------- 60 | // Initializes the GPIOs 61 | //---------------------------------------------------------------------------- 62 | void GPIO_init(void); 63 | 64 | //---------------------------------------------------------------------------- 65 | // Initializes the PWM 66 | //---------------------------------------------------------------------------- 67 | void PWM_init(void); 68 | 69 | //---------------------------------------------------------------------------- 70 | // Initializes the ADC 71 | //---------------------------------------------------------------------------- 72 | void ADC_init(void); 73 | 74 | //---------------------------------------------------------------------------- 75 | // Initializes the usart master slave 76 | //---------------------------------------------------------------------------- 77 | void USART_MasterSlave_init(void); 78 | 79 | //---------------------------------------------------------------------------- 80 | // Initializes the steer/bluetooth usart 81 | //---------------------------------------------------------------------------- 82 | void USART_Steer_COM_init(void); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/gd32f1x0_dbg.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file gd32f1x0_dbg.c 3 | \brief DBG driver 4 | */ 5 | 6 | /* 7 | Copyright (C) 2017 GigaDevice 8 | 9 | 2014-12-26, V1.0.0, platform GD32F1x0(x=3,5) 10 | 2016-01-15, V2.0.0, platform GD32F1x0(x=3,5,7,9) 11 | 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | */ 14 | 15 | #include "gd32f1x0_dbg.h" 16 | 17 | #define DBG_RESET_VAL 0x00000000U 18 | 19 | /*! 20 | \brief deinitialize the DBG 21 | \param[in] none 22 | \param[out] none 23 | \retval none 24 | */ 25 | void dbg_deinit(void) 26 | { 27 | DBG_CTL0 = DBG_RESET_VAL; 28 | DBG_CTL1 = DBG_RESET_VAL; 29 | } 30 | 31 | /*! 32 | \brief read DBG_ID code register 33 | \param[in] none 34 | \param[out] none 35 | \retval DBG_ID code 36 | */ 37 | uint32_t dbg_id_get(void) 38 | { 39 | return DBG_ID; 40 | } 41 | 42 | /*! 43 | \brief enable low power behavior when the mcu is in debug mode 44 | \param[in] dbg_low_power: 45 | this parameter can be any combination of the following values: 46 | \arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode 47 | \arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode 48 | \arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode 49 | \param[out] none 50 | \retval none 51 | */ 52 | void dbg_low_power_enable(uint32_t dbg_low_power) 53 | { 54 | DBG_CTL0 |= dbg_low_power; 55 | } 56 | 57 | /*! 58 | \brief disable low power behavior when the mcu is in debug mode 59 | \param[in] dbg_low_power: 60 | this parameter can be any combination of the following values: 61 | \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode 62 | \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode 63 | \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode 64 | \param[out] none 65 | \retval none 66 | */ 67 | void dbg_low_power_disable(uint32_t dbg_low_power) 68 | { 69 | DBG_CTL0 &= ~dbg_low_power; 70 | } 71 | 72 | /*! 73 | \brief enable peripheral behavior when the mcu is in debug mode 74 | \param[in] dbg_periph: refer to dbg_periph_enum 75 | only one parameter can be selected which is shown as below: 76 | \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted 77 | \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted 78 | \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted(170_190 series only) 79 | \arg DBG_I2Cx_HOLD (x=0,1,2): hold I2Cx smbus when core is halted 80 | \arg DBG_TIMERx_HOLD (x=0,1,2,5,13,14,15,16): hold TIMERx counter when core is halted 81 | \arg DBG_RTC_HOLD : hold RTC calendar and wakeup counter when core is halted 82 | \param[out] none 83 | \retval none 84 | */ 85 | void dbg_periph_enable(dbg_periph_enum dbg_periph) 86 | { 87 | DBG_REG_VAL(dbg_periph) |= BIT(DBG_BIT_POS(dbg_periph)); 88 | } 89 | 90 | /*! 91 | \brief disable peripheral behavior when the mcu is in debug mode 92 | \param[in] dbg_periph: refer to dbg_periph_enum 93 | only one parameter can be selected which is shown as below: 94 | \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted 95 | \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted 96 | \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted(170_190 series only) 97 | \arg DBG_I2Cx_HOLD (x=0,1,2): hold I2Cx smbus when core is halted 98 | \arg DBG_TIMERx_HOLD (x=0,1,2,5,13,14,15,16): hold TIMERx counter when core is halted 99 | \arg DBG_RTC_HOLD : hold RTC calendar and wakeup counter when core is halted 100 | \param[out] none 101 | \retval none 102 | */ 103 | void dbg_periph_disable(dbg_periph_enum dbg_periph) 104 | { 105 | DBG_REG_VAL(dbg_periph) &= ~BIT(DBG_BIT_POS(dbg_periph)); 106 | } 107 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/gd32f1x0_fwdgt.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file gd32f1x0_fwdgt.c 3 | \brief FWDGT driver 4 | */ 5 | 6 | /* 7 | Copyright (C) 2017 GigaDevice 8 | 9 | 2014-12-26, V1.0.0, platform GD32F1x0(x=3,5) 10 | 2016-01-15, V2.0.0, platform GD32F1x0(x=3,5,7,9) 11 | 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | */ 14 | 15 | #include "gd32f1x0_fwdgt.h" 16 | 17 | /*! 18 | \brief disable write access to FWDGT_PSC,FWDGT_RLD and FWDGT_WND 19 | \param[in] none 20 | \param[out] none 21 | \retval none 22 | */ 23 | void fwdgt_write_disable(void) 24 | { 25 | FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; 26 | } 27 | 28 | /*! 29 | \brief reload the counter of FWDGT 30 | \param[in] none 31 | \param[out] none 32 | \retval none 33 | */ 34 | void fwdgt_counter_reload(void) 35 | { 36 | FWDGT_CTL = FWDGT_KEY_RELOAD; 37 | } 38 | 39 | /*! 40 | \brief start the free watchdog timer counter 41 | \param[in] none 42 | \param[out] none 43 | \retval none 44 | */ 45 | void fwdgt_enable(void) 46 | { 47 | FWDGT_CTL = FWDGT_KEY_ENABLE; 48 | } 49 | 50 | /*! 51 | \brief configure the free watchdog timer counter window value 52 | \param[in] window_value: specify window value(0x0000 - 0x0FFF) 53 | \param[out] none 54 | \retval ErrStatus: ERROR or SUCCESS 55 | */ 56 | ErrStatus fwdgt_window_value_config(uint16_t window_value) 57 | { 58 | uint32_t time_index = FWDGT_WND_TIMEOUT; 59 | uint32_t flag_status = RESET; 60 | 61 | /* enable write access to FWDGT_WND */ 62 | FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; 63 | 64 | /* wait until the WUD flag to be reset */ 65 | do{ 66 | flag_status = FWDGT_STAT & FWDGT_STAT_WUD; 67 | }while((--time_index > 0U) && ((uint32_t)RESET != flag_status)); 68 | 69 | if ((uint32_t)RESET != flag_status){ 70 | return ERROR; 71 | } 72 | 73 | FWDGT_WND = WND_WND(window_value); 74 | 75 | return SUCCESS; 76 | } 77 | 78 | /*! 79 | \brief configure counter reload value, and prescaler divider value 80 | \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) 81 | \param[in] prescaler_div: FWDGT prescaler value 82 | \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 83 | \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 84 | \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 85 | \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 86 | \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 87 | \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 88 | \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 89 | \param[out] none 90 | \retval ErrStatus: ERROR or SUCCESS 91 | */ 92 | ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) 93 | { 94 | uint32_t timeout = FWDGT_PSC_TIMEOUT; 95 | uint32_t flag_status = RESET; 96 | 97 | /* enable write access to FWDGT_PSC,and FWDGT_RLD */ 98 | FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; 99 | 100 | /* wait until the PUD flag to be reset */ 101 | do{ 102 | flag_status = FWDGT_STAT & FWDGT_STAT_PUD; 103 | }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); 104 | 105 | if ((uint32_t)RESET != flag_status){ 106 | return ERROR; 107 | } 108 | 109 | /* configure FWDGT */ 110 | FWDGT_PSC = (uint32_t)prescaler_div; 111 | 112 | timeout = FWDGT_RLD_TIMEOUT; 113 | /* wait until the RUD flag to be reset */ 114 | do{ 115 | flag_status = FWDGT_STAT & FWDGT_STAT_RUD; 116 | }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); 117 | 118 | if ((uint32_t)RESET != flag_status){ 119 | return ERROR; 120 | } 121 | 122 | FWDGT_RLD = RLD_RLD(reload_value); 123 | 124 | /* reload the counter */ 125 | FWDGT_CTL = FWDGT_KEY_RELOAD; 126 | 127 | return SUCCESS; 128 | } 129 | 130 | /*! 131 | \brief get flag state of FWDGT 132 | \param[in] flag: flag to get 133 | \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going 134 | \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going 135 | \arg FWDGT_FLAG_WUD: a write operation to FWDGT_WND register is on going 136 | \param[out] none 137 | \retval FlagStatus: SET or RESET 138 | */ 139 | FlagStatus fwdgt_flag_get(uint16_t flag) 140 | { 141 | if(FWDGT_STAT & flag){ 142 | return SET; 143 | } 144 | 145 | return RESET; 146 | } 147 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/gd32f1x0_gpio.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file gd32f1x0_gpio.c 3 | \brief GPIO driver 4 | */ 5 | 6 | /* 7 | Copyright (C) 2017 GigaDevice 8 | 9 | 2014-12-26, V1.0.0, platform for GD32F1x0(x=3,5) 10 | 2016-01-15, V2.0.0, platform for GD32F1x0(x=3,5,7,9) 11 | 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | */ 14 | 15 | #include "gd32f1x0_gpio.h" 16 | 17 | /*! 18 | \brief reset GPIO port 19 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 20 | \param[out] none 21 | \retval none 22 | */ 23 | void gpio_deinit(uint32_t gpio_periph) 24 | { 25 | switch(gpio_periph){ 26 | case GPIOA: 27 | /* reset GPIOA */ 28 | rcu_periph_reset_enable(RCU_GPIOARST); 29 | rcu_periph_reset_disable(RCU_GPIOARST); 30 | break; 31 | case GPIOB: 32 | /* reset GPIOB */ 33 | rcu_periph_reset_enable(RCU_GPIOBRST); 34 | rcu_periph_reset_disable(RCU_GPIOBRST); 35 | break; 36 | case GPIOC: 37 | /* reset GPIOC */ 38 | rcu_periph_reset_enable(RCU_GPIOCRST); 39 | rcu_periph_reset_disable(RCU_GPIOCRST); 40 | break; 41 | case GPIOD: 42 | /* reset GPIOD */ 43 | rcu_periph_reset_enable(RCU_GPIODRST); 44 | rcu_periph_reset_disable(RCU_GPIODRST); 45 | break; 46 | case GPIOF: 47 | /* reset GPIOF */ 48 | rcu_periph_reset_enable(RCU_GPIOFRST); 49 | rcu_periph_reset_disable(RCU_GPIOFRST); 50 | break; 51 | default: 52 | break; 53 | } 54 | } 55 | 56 | /*! 57 | \brief set GPIO output mode 58 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 59 | \param[in] mode: gpio pin mode 60 | \arg GPIO_MODE_INPUT: input mode 61 | \arg GPIO_MODE_OUTPUT: output mode 62 | \arg GPIO_MODE_AF: alternate function mode 63 | \arg GPIO_MODE_ANALOG: analog mode 64 | \param[in] pull_up_down: gpio pin with pull-up or pull-down resistor 65 | \arg GPIO_PUPD_NONE: without weak pull-up and pull-down resistors 66 | \arg GPIO_PUPD_PULLUP: with weak pull-up resistor 67 | \arg GPIO_PUPD_PULLDOWN:with weak pull-down resistor 68 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 69 | \param[out] none 70 | \retval none 71 | */ 72 | void gpio_mode_set(uint32_t gpio_periph,uint32_t mode,uint32_t pull_up_down,uint32_t pin) 73 | { 74 | uint16_t i; 75 | uint32_t ctl, pupd; 76 | 77 | ctl = GPIO_CTL(gpio_periph); 78 | pupd = GPIO_PUD(gpio_periph); 79 | 80 | for (i = 0U; i < 16U; i++){ 81 | if((1U << i) & pin){ 82 | /* clear the specified pin mode bits */ 83 | ctl &= ~GPIO_MODE_MASK(i); 84 | /* set the specified pin mode bits */ 85 | ctl |= GPIO_MODE_SET(i, mode); 86 | 87 | /* clear the specified pin pupd bits */ 88 | pupd &= ~GPIO_PUPD_MASK(i); 89 | /* set the specified pin pupd bits */ 90 | pupd |= GPIO_PUPD_SET(i, pull_up_down); 91 | } 92 | } 93 | 94 | GPIO_CTL(gpio_periph) = ctl; 95 | GPIO_PUD(gpio_periph) = pupd; 96 | } 97 | 98 | /*! 99 | \brief set GPIO output type and speed 100 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 101 | \param[in] otype: gpio pin output mode 102 | \arg GPIO_OTYPE_PP: push pull mode 103 | \arg GPIO_OTYPE_OD: open drain mode 104 | \param[in] speed 105 | \arg GPIO_OSPEED_2MHZ: output max speed 2M 106 | \arg GPIO_OSPEED_10MHZ: output max speed 10M 107 | \arg GPIO_OSPEED_50MHZ: output max speed 50M 108 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 109 | \param[out] none 110 | \retval none 111 | */ 112 | void gpio_output_options_set(uint32_t gpio_periph,uint8_t otype,uint32_t speed,uint32_t pin) 113 | { 114 | uint16_t i; 115 | uint32_t ospeedr; 116 | 117 | if(0x1U == otype){ 118 | GPIO_OMODE(gpio_periph) |= (uint32_t)pin; 119 | }else{ 120 | GPIO_OMODE(gpio_periph) &= (uint32_t)(~pin); 121 | } 122 | 123 | /* get the specified pin output speed bits value */ 124 | ospeedr = GPIO_OSPD(gpio_periph); 125 | 126 | for(i = 0U;i < 16U;i++){ 127 | if((1U << i) & pin){ 128 | /* clear the specified pin output speed bits */ 129 | ospeedr &= ~GPIO_OSPEED_MASK(i); 130 | /* set the specified pin output speed bits */ 131 | ospeedr |= GPIO_OSPEED_SET(i,speed); 132 | } 133 | } 134 | GPIO_OSPD(gpio_periph) = ospeedr; 135 | } 136 | 137 | /*! 138 | \brief set GPIO pin 139 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 140 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 141 | \param[out] none 142 | \retval none 143 | */ 144 | void gpio_bit_set(uint32_t gpio_periph,uint32_t pin) 145 | { 146 | GPIO_BOP(gpio_periph) = (uint32_t)pin; 147 | } 148 | 149 | /*! 150 | \brief reset GPIO pin 151 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 152 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 153 | \param[out] none 154 | \retval none 155 | */ 156 | void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin) 157 | { 158 | GPIO_BC(gpio_periph) = (uint32_t)pin; 159 | } 160 | 161 | /*! 162 | \brief write data to the specified GPIO pin 163 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 164 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 165 | \param[in] bit_value: SET or RESET 166 | \arg RESET: clear the port pin 167 | \arg SET: set the port pin 168 | \param[out] none 169 | \retval none 170 | */ 171 | void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value) 172 | { 173 | if(RESET != bit_value){ 174 | GPIO_BOP(gpio_periph) = (uint32_t)pin; 175 | }else{ 176 | GPIO_BC(gpio_periph) = (uint32_t)pin; 177 | } 178 | } 179 | 180 | /*! 181 | \brief write data to the specified GPIO port 182 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 183 | \param[in] data: specify the value to be written to the port output control register 184 | \param[out] none 185 | \retval none 186 | */ 187 | void gpio_port_write(uint32_t gpio_periph,uint16_t data) 188 | { 189 | GPIO_OCTL(gpio_periph) = (uint32_t)data; 190 | } 191 | 192 | /*! 193 | \brief get GPIO pin input status 194 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 195 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 196 | \param[out] none 197 | \retval input state of gpio pin: SET or RESET 198 | */ 199 | FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) 200 | { 201 | if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ 202 | return SET; 203 | }else{ 204 | return RESET; 205 | } 206 | } 207 | 208 | /*! 209 | \brief get GPIO all pins input status 210 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 211 | \param[out] none 212 | \retval input state of gpio all pins 213 | */ 214 | uint16_t gpio_input_port_get(uint32_t gpio_periph) 215 | { 216 | return (uint16_t)(GPIO_ISTAT(gpio_periph)); 217 | } 218 | 219 | /*! 220 | \brief get GPIO pin output status 221 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 222 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 223 | \param[out] none 224 | \retval output state of gpio pin: SET or RESET 225 | */ 226 | FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin) 227 | { 228 | if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ 229 | return SET; 230 | }else{ 231 | return RESET; 232 | } 233 | } 234 | 235 | /*! 236 | \brief get GPIO all pins output status 237 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 238 | \param[out] none 239 | \retval output state of gpio all pins 240 | */ 241 | uint16_t gpio_output_port_get(uint32_t gpio_periph) 242 | { 243 | return ((uint16_t)GPIO_OCTL(gpio_periph)); 244 | } 245 | 246 | /*! 247 | \brief set GPIO alternate function 248 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 249 | \param[in] alt_func_num: gpio pin af function, please refer to specific device datasheet 250 | \arg GPIO_AF_0: TIMER2, TIMER13, TIMER14, TIMER16, SPI0, I2S0, SPI1, SPI2, I2S2, CK_OUT, 251 | SWDIO, SWCLK, USART0, CEC, IFRP, I2C0, I2C1, TSI, EVENTOUT 252 | \arg GPIO_AF_1: USART0, USART1, IFRP, CEC, TIMER2, TIMER14, I2C0, I2C1, I2C2, EVENTOUT 253 | \arg GPIO_AF_2: TIMER0, TIMER1, TIMER15, TIMER16, EVENTOUT 254 | \arg GPIO_AF_3: TSI, I2C0, TIMER14, EVENTOUT 255 | \arg GPIO_AF_4(port A,B only): TIMER13, I2C0, I2C1, I2C2, USART1 256 | \arg GPIO_AF_5(port A,B only): TIMER15, TIMER16, SPI2, I2S2, I2C0, I2C1 257 | \arg GPIO_AF_6(port A,B only): SPI1, EVENTOUT 258 | \arg GPIO_AF_7(port A,B only): CMP0, CMP1 259 | \arg GPIO_AF_9(port A,B only): CAN0, CAN1 (for GD32F170xx and GD32F190xx devices) 260 | \arg GPIO_AF_11: SLCD (for GD32F170xx and GD32F190xx devices) 261 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 262 | \param[out] none 263 | \retval none 264 | */ 265 | void gpio_af_set(uint32_t gpio_periph,uint32_t alt_func_num,uint32_t pin) 266 | { 267 | uint16_t i; 268 | uint32_t afrl, afrh; 269 | 270 | afrl = GPIO_AFSEL0(gpio_periph); 271 | afrh = GPIO_AFSEL1(gpio_periph); 272 | 273 | for (i = 0U; i < 8U; i++){ 274 | if((1U << i) & pin){ 275 | /* clear the specified pin alternate function bits */ 276 | afrl &= ~GPIO_AFR_MASK(i); 277 | afrl |= GPIO_AFR_SET(i,alt_func_num); 278 | } 279 | } 280 | 281 | for (i = 8U; i < 16U; i++){ 282 | if((1U << i) & pin){ 283 | /* clear the specified pin alternate function bits */ 284 | afrh &= ~GPIO_AFR_MASK(i - 8U); 285 | afrh |= GPIO_AFR_SET(i - 8U,alt_func_num); 286 | } 287 | } 288 | 289 | GPIO_AFSEL0(gpio_periph) = afrl; 290 | GPIO_AFSEL1(gpio_periph) = afrh; 291 | } 292 | 293 | /*! 294 | \brief lock GPIO pin 295 | \param[in] gpio_periph: GPIOx(x = A,B) 296 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 297 | \param[out] none 298 | \retval none 299 | */ 300 | void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) 301 | { 302 | uint32_t lock = 0x00010000U; 303 | lock |= pin; 304 | 305 | /* lock key writing sequence: write 1->write 0->write 1-> read 0-> read 1 */ 306 | GPIO_LOCK(gpio_periph) = (uint32_t)lock; 307 | GPIO_LOCK(gpio_periph) = (uint32_t)pin; 308 | GPIO_LOCK(gpio_periph) = (uint32_t)lock; 309 | lock = GPIO_LOCK(gpio_periph); 310 | lock = GPIO_LOCK(gpio_periph); 311 | } 312 | 313 | #ifdef GD32F170_190 314 | /*! 315 | \brief toggle GPIO pin 316 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 317 | \param[in] pin: GPIO_PIN_x(x=0..15), GPIO_PIN_ALL 318 | \param[out] none 319 | \retval none 320 | */ 321 | void gpio_bit_toggle(uint32_t gpio_periph,uint32_t pin) 322 | { 323 | GPIO_TG(gpio_periph) = (uint32_t)pin; 324 | } 325 | 326 | /*! 327 | \brief toggle GPIO port 328 | \param[in] gpio_periph: GPIOx(x = A,B,C,D,F) 329 | \param[out] none 330 | \retval none 331 | */ 332 | void gpio_port_toggle(uint32_t gpio_periph) 333 | { 334 | GPIO_TG(gpio_periph) = 0x0000FFFFU; 335 | } 336 | 337 | #endif /* GD32F170_190 */ 338 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/gd32f1x0_misc.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file gd32f1x0_misc.c 3 | \brief MISC driver 4 | */ 5 | 6 | /* 7 | Copyright (C) 2017 GigaDevice 8 | 9 | 2014-12-26, V1.0.0, platform GD32F1x0(x=3,5) 10 | 2016-01-15, V2.0.0, platform GD32F1x0(x=3,5,7,9) 11 | 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | */ 14 | 15 | #include "gd32f1x0_misc.h" 16 | 17 | /*! 18 | \brief set the priority group 19 | \param[in] nvic_prigroup: the NVIC priority group 20 | \arg NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority 21 | \arg NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority 22 | \arg NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority 23 | \arg NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority 24 | \arg NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority 25 | \param[out] none 26 | \retval none 27 | */ 28 | void nvic_priority_group_set(uint32_t nvic_prigroup) 29 | { 30 | /* set the priority group value */ 31 | SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup; 32 | } 33 | 34 | /*! 35 | \brief enable NVIC request 36 | \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type 37 | \param[in] nvic_irq_pre_priority: the pre-emption priority needed to set 38 | \param[in] nvic_irq_sub_priority: the subpriority needed to set 39 | \param[out] none 40 | \retval none 41 | */ 42 | void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, 43 | uint8_t nvic_irq_sub_priority) 44 | { 45 | uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; 46 | /* use the priority group value to get the temp_pre and the temp_sub */ 47 | if(((SCB->AIRCR) & (uint32_t)0x700)==NVIC_PRIGROUP_PRE0_SUB4){ 48 | temp_pre = 0U; 49 | temp_sub = 0x4U; 50 | }else if(((SCB->AIRCR) & (uint32_t)0x700)==NVIC_PRIGROUP_PRE1_SUB3){ 51 | temp_pre = 1U; 52 | temp_sub = 0x3U; 53 | }else if(((SCB->AIRCR) & (uint32_t)0x700)==NVIC_PRIGROUP_PRE2_SUB2){ 54 | temp_pre = 2U; 55 | temp_sub = 0x2U; 56 | }else if(((SCB->AIRCR) & (uint32_t)0x700)==NVIC_PRIGROUP_PRE3_SUB1){ 57 | temp_pre = 3U; 58 | temp_sub = 0x1U; 59 | }else if(((SCB->AIRCR) & (uint32_t)0x700)==NVIC_PRIGROUP_PRE4_SUB0){ 60 | temp_pre = 4U; 61 | temp_sub = 0x0U; 62 | }else{ 63 | } 64 | /* get the temp_priority to fill the NVIC->IP register */ 65 | temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); 66 | temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub)); 67 | temp_priority = temp_priority << 0x04U; 68 | NVIC->IP[nvic_irq] = (uint8_t)temp_priority; 69 | /* enable the selected IRQ */ 70 | NVIC->ISER[nvic_irq >> 0x05] = (uint32_t)0x01 << (nvic_irq & (uint8_t)0x1F); 71 | } 72 | 73 | /*! 74 | \brief disable NVIC request 75 | \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type 76 | \param[out] none 77 | \retval none 78 | */ 79 | void nvic_irq_disable(uint8_t nvic_irq) 80 | { 81 | /* disable the selected IRQ.*/ 82 | NVIC->ICER[nvic_irq >> 0x05] = (uint32_t)0x01 << (nvic_irq & (uint8_t)0x1F); 83 | } 84 | 85 | /*! 86 | \brief set the NVIC vector table base address 87 | \param[in] nvic_vict_tab: the RAM or FLASH base address 88 | \arg NVIC_VECTTAB_RAM: RAM base address 89 | \are NVIC_VECTTAB_FLASH: Flash base address 90 | \param[in] offset: Vector Table offset 91 | \param[out] none 92 | \retval none 93 | */ 94 | void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) 95 | { 96 | SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK); 97 | } 98 | 99 | /*! 100 | \brief set the state of the low power mode 101 | \param[in] lowpower_mode: the low power mode state 102 | \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power 103 | mode by exiting from ISR 104 | \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode 105 | \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up 106 | by all the enable and disable interrupts 107 | \param[out] none 108 | \retval none 109 | */ 110 | void system_lowpower_set(uint8_t lowpower_mode) 111 | { 112 | SCB->SCR |= (uint32_t)lowpower_mode; 113 | } 114 | 115 | /*! 116 | \brief reset the state of the low power mode 117 | \param[in] lowpower_mode: the low power mode state 118 | \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power 119 | mode by exiting from ISR 120 | \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode 121 | \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be 122 | woke up by the enable interrupts 123 | \param[out] none 124 | \retval none 125 | */ 126 | void system_lowpower_reset(uint8_t lowpower_mode) 127 | { 128 | SCB->SCR &= (~(uint32_t)lowpower_mode); 129 | } 130 | 131 | /*! 132 | \brief set the systick clock source 133 | \param[in] systick_clksource: the systick clock source needed to choose 134 | \arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK 135 | \arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8 136 | \param[out] none 137 | \retval none 138 | */ 139 | 140 | void systick_clksource_set(uint32_t systick_clksource) 141 | { 142 | if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){ 143 | /* set the systick clock source from HCLK */ 144 | SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; 145 | }else{ 146 | /* set the systick clock source from HCLK/8 */ 147 | SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/gd32f1x0_opa.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file gd32f1x0_opa.c 3 | \brief OPA driver 4 | */ 5 | 6 | /* 7 | Copyright (C) 2017 GigaDevice 8 | 9 | 2014-12-26, V1.0.0, platform GD32F1x0(x=3,5) 10 | 2016-01-15, V2.0.0, platform GD32F1x0(x=3,5,7,9) 11 | 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | */ 14 | 15 | #ifdef GD32F170_190 16 | 17 | #include "gd32f1x0_opa.h" 18 | 19 | /*! 20 | \brief deinit the OPA register to its default reset value 21 | \param[in] none 22 | \param[out] none 23 | \retval none 24 | */ 25 | void opa_deinit(void) 26 | { 27 | rcu_periph_reset_enable(RCU_OPAIVREFRST); 28 | rcu_periph_reset_disable(RCU_OPAIVREFRST); 29 | } 30 | 31 | /*! 32 | \brief enable OPA switch 33 | \param[in] opax_swy 34 | \arg OPA_T3OPA0: T3 switch enable for OPA0 35 | \arg OPA_S1OPA0: S1 switch enable for OPA0 36 | \arg OPA_S2OPA0: S2 switch enable for OPA0 37 | \arg OPA_S3OPA0: S3 switch enable for OPA0 38 | \arg OPA_T3OPA1: T3 switch enable for OPA1 39 | \arg OPA_S1OPA1: S1 switch enable for OPA1 40 | \arg OPA_S2OPA1: S2 switch enable for OPA1 41 | \arg OPA_S3OPA1: S3 switch enable for OPA1 42 | \arg OPA_S4OPA1: S4 switch enable for OPA1 43 | \arg OPA_T3OPA2: T3 switch enable for OPA2 44 | \arg OPA_S1OPA2: S3 switch enable for OPA2 45 | \arg OPA_S2OPA2: S3 switch enable for OPA2 46 | \arg OPA_S3OPA2: S3 switch enable for OPA2 47 | \param[out] none 48 | \retval none 49 | */ 50 | void opa_switch_enable(uint32_t opax_swy) 51 | { 52 | OPA_CTL |= (uint32_t)(opax_swy); 53 | } 54 | 55 | /*! 56 | \brief enable OPA 57 | \param[in] opa_periph 58 | \arg OPAx(x =0,1,2) 59 | \param[out] none 60 | \retval none 61 | */ 62 | void opa_enable(uint32_t opa_periph) 63 | { 64 | if(OPA0 == opa_periph){ 65 | OPA_CTL &= ~OPA_CTL_OPA0PD; 66 | }else if(OPA1 == opa_periph){ 67 | OPA_CTL &= ~OPA_CTL_OPA1PD; 68 | }else{ 69 | OPA_CTL &= ~OPA_CTL_OPA2PD; 70 | } 71 | } 72 | 73 | /*! 74 | \brief disable OPA 75 | \param[in] opa_periph 76 | \arg OPAx(x =0,1,2) 77 | \param[out] none 78 | \retval none 79 | */ 80 | void opa_disable(uint32_t opa_periph) 81 | { 82 | if(OPA0 == opa_periph){ 83 | OPA_CTL |= OPA_CTL_OPA0PD; 84 | }else if(OPA1 == opa_periph){ 85 | OPA_CTL |= OPA_CTL_OPA1PD; 86 | }else{ 87 | OPA_CTL |= OPA_CTL_OPA2PD; 88 | } 89 | } 90 | 91 | /*! 92 | \brief disable OPA switch 93 | \param[in] opax_swy 94 | \arg OPA_T3OPA0: T3 switch enable for OPA0 95 | \arg OPA_S1OPA0: S1 switch enable for OPA0 96 | \arg OPA_S2OPA0: S2 switch enable for OPA0 97 | \arg OPA_S3OPA0: S3 switch enable for OPA0 98 | \arg OPA_T3OPA1: T3 switch enable for OPA1 99 | \arg OPA_S1OPA1: S1 switch enable for OPA1 100 | \arg OPA_S2OPA1: S2 switch enable for OPA1 101 | \arg OPA_S3OPA1: S3 switch enable for OPA1 102 | \arg OPA_S4OPA1: S4 switch enable for OPA1 103 | \arg OPA_T3OPA2: T3 switch enable for OPA2 104 | \arg OPA_S1OPA2: S3 switch enable for OPA2 105 | \arg OPA_S2OPA2: S3 switch enable for OPA2 106 | \arg OPA_S3OPA2: S3 switch enable for OPA2 107 | \param[out] none 108 | \retval none 109 | */ 110 | void opa_switch_disable(uint32_t opax_swy) 111 | { 112 | OPA_CTL &= ~opax_swy; 113 | } 114 | 115 | /*! 116 | \brief enable OPA in low power mode 117 | \param[in] opa_periph 118 | \arg OPAx(x =0,1,2) 119 | \param[out] none 120 | \retval none 121 | */ 122 | void opa_low_power_enable(uint32_t opa_periph) 123 | { 124 | if(OPA0 == opa_periph){ 125 | OPA_CTL &= ~OPA_CTL_OPA0LPM; 126 | }else if(OPA1 == opa_periph){ 127 | OPA_CTL &= ~OPA_CTL_OPA1LPM; 128 | }else{ 129 | OPA_CTL &= ~OPA_CTL_OPA2LPM; 130 | } 131 | } 132 | 133 | /*! 134 | \brief disable OPA in low power mode 135 | \param[in] opa_periph 136 | \arg OPAx(x =0,1,2) 137 | \param[out] none 138 | \retval none 139 | */ 140 | void opa_low_power_disable(uint32_t opa_periph) 141 | { 142 | if(OPA0 == opa_periph){ 143 | OPA_CTL |= OPA_CTL_OPA0LPM; 144 | }else if(OPA1 == opa_periph){ 145 | OPA_CTL |= OPA_CTL_OPA1LPM; 146 | }else{ 147 | OPA_CTL |= OPA_CTL_OPA2LPM; 148 | } 149 | } 150 | 151 | /*! 152 | \brief set OPA power range 153 | \param[in] powerrange 154 | \arg OPA_POWRANGE_LOW: Low power range is selected (VDDA is lower than 3.3V) 155 | \arg OPA_POWRANGE_HIGH: High power range is selected (VDDA is higher than 3.3V) 156 | \param[out] none 157 | \retval none 158 | */ 159 | void opa_power_range_config(uint32_t powerrange) 160 | { 161 | OPA_CTL &= ~OPA_CTL_OPA_RANGE; 162 | OPA_CTL |= powerrange; 163 | } 164 | 165 | /*! 166 | \brief set OPA bias trimming mode 167 | \param[in] opa_trimmode 168 | \arg OPA_BT_TRIM_FACTORY: factory trimming values are used for offset calibration 169 | \arg OPA_BT_TRIM_USER: user trimming values are used for offset calibration 170 | \param[out] none 171 | \retval none 172 | */ 173 | void opa_trim_mode_set(uint32_t opa_trimmode) 174 | { 175 | OPA_BT &= ~OPA_BT_OT_USER; 176 | OPA_BT |= opa_trimmode; 177 | } 178 | 179 | /*! 180 | \brief set OPA bias trimming value 181 | \param[in] opa_periph 182 | \arg OPAx(x =0,1,2) 183 | \param[in] opa_input 184 | \arg OPA_INPUT_P: PMOS input is selected to configure the trimming value 185 | \arg OPA_INPUT_N: NMOS input is selected to configure the trimming value 186 | \param[in] opa_trimmode 187 | \arg this parameter can be any value lower or equal to 0x0000001F. 188 | \param[out] none 189 | \retval none 190 | */ 191 | void opa_trim_value_config(uint32_t opa_periph,uint32_t opa_input,uint32_t opa_trimvalue) 192 | { 193 | uint32_t bt = 0U, ctl = 0U; 194 | ctl = OPA_CTL; 195 | bt = OPA_BT; 196 | 197 | if(OPA0 == opa_periph){ 198 | /* clear the specified opa calibration for N diff and P diff */ 199 | ctl &= (uint32_t)~(OPA_CTL_OPA0CAL_L | OPA_CTL_OPA0CAL_H); 200 | /* set the specified opa calibration for N diff or P diff */ 201 | ctl |= opa_input; 202 | if(OPA_INPUT_P == opa_input){ 203 | /* clear the specified PMOS pairs normal mode 5-bit offset trim value */ 204 | bt &= (~OPA_BT_OA0_TRIM_LOW); 205 | bt |= (opa_trimvalue); 206 | }else{ 207 | /* clear the specified NMOS pairs normal mode 5-bit offset trim value */ 208 | bt &= (~OPA_BT_OA0_TRIM_HIGH); 209 | bt |= (opa_trimvalue << 5U); 210 | } 211 | 212 | }else if(OPA1 == opa_periph){ 213 | ctl &= (uint32_t)~(OPA_CTL_OPA1CAL_L | OPA_CTL_OPA1CAL_H); 214 | ctl |= (uint32_t)(opa_input << 8U); 215 | if(OPA_INPUT_P == opa_input){ 216 | /* clear the specified PMOS pairs normal mode 5-bit offset trim value */ 217 | bt &= (~OPA_BT_OA1_TRIM_LOW); 218 | bt |= (opa_trimvalue << 10U); 219 | }else{ 220 | /* clear the specified NMOS pairs normal mode 5-bit offset trim value */ 221 | bt &= (~OPA_BT_OA1_TRIM_HIGH); 222 | bt |= (opa_trimvalue << 15U); 223 | } 224 | }else{ 225 | ctl &= (uint32_t)~(OPA_CTL_OPA2CAL_L | OPA_CTL_OPA2CAL_H); 226 | ctl |= (uint32_t)(opa_input << 16U); 227 | if(OPA_INPUT_P == opa_input){ 228 | /* clear the specified PMOS pairs normal mode 5-bit offset trim value */ 229 | bt &= (~OPA_BT_OA2_TRIM_LOW); 230 | bt |= (opa_trimvalue << 20U); 231 | }else{ 232 | /* clear the specified NMOS pairs normal mode 5-bit offset trim value */ 233 | bt &= (~OPA_BT_OA2_TRIM_HIGH); 234 | bt |= (opa_trimvalue << 25U); 235 | } 236 | } 237 | 238 | OPA_CTL = ctl; 239 | OPA_BT = bt; 240 | } 241 | 242 | /*! 243 | \brief set OPA bias trimming value low power 244 | \param[in] opa_periph 245 | \arg OPAx(x =0,1,2) 246 | \param[in] opa_input 247 | \arg OPA_INPUT_P: PMOS input is selected to configure the trimming value 248 | \arg OPA_INPUT_N: NMOS input is selected to configure the trimming value 249 | \param[in] opa_trimmode 250 | \arg this parameter can be any value lower or equal to 0x0000001F. 251 | \param[out] none 252 | \retval none 253 | */ 254 | void opa_trim_value_lp_config(uint32_t opa_periph,uint32_t opa_input,uint32_t opa_trimvalue) 255 | { 256 | uint32_t lpbt = 0U, ctl = 0U; 257 | ctl = OPA_CTL; 258 | lpbt = OPA_LPBT; 259 | 260 | if(OPA0 == opa_periph){ 261 | ctl &= (uint32_t)~(OPA_CTL_OPA0CAL_L | OPA_CTL_OPA0CAL_H); 262 | ctl |= opa_input; 263 | if(OPA_INPUT_P == opa_input){ 264 | /* clear the specified PMOS pairs low power mode 5-bit offset trim value */ 265 | lpbt &= (~OPA_LPBT_OA0_TRIM_LOW); 266 | lpbt |= (opa_trimvalue); 267 | }else{ 268 | /* clear the specified NMOS pairs low power mode 5-bit offset trim value */ 269 | lpbt &= (~OPA_LPBT_OA0_TRIM_HIGH); 270 | lpbt |= (opa_trimvalue << 5U); 271 | } 272 | }else if (OPA1 == opa_periph){ 273 | ctl &= (uint32_t)~(OPA_CTL_OPA0CAL_L | OPA_CTL_OPA0CAL_H); 274 | ctl |= (uint32_t)(opa_input << 8U); 275 | if(OPA_INPUT_P == opa_input){ 276 | /* clear the specified PMOS pairs low power mode 5-bit offset trim value */ 277 | lpbt &= (~OPA_LPBT_OA1_TRIM_LOW); 278 | lpbt |= (opa_trimvalue << 10U); 279 | }else{ 280 | /* clear the specified NMOS pairs low power mode 5-bit offset trim value */ 281 | lpbt &= (~OPA_LPBT_OA1_TRIM_HIGH); 282 | lpbt |= (opa_trimvalue << 15U); 283 | } 284 | 285 | }else{ 286 | ctl &= (uint32_t)~(OPA_CTL_OPA2CAL_L | OPA_CTL_OPA2CAL_H); 287 | ctl |= (uint32_t)(opa_input << 16U); 288 | if(OPA_INPUT_P == opa_input){ 289 | /* clear the specified PMOS pairs low power mode 5-bit offset trim value */ 290 | lpbt &= (~OPA_LPBT_OA2_TRIM_LOW); 291 | lpbt |= (opa_trimvalue << 20U); 292 | }else{ 293 | /* clear the specified NMOS pairs low power mode 5-bit offset trim value */ 294 | lpbt &= (~OPA_LPBT_OA2_TRIM_HIGH); 295 | lpbt |= (opa_trimvalue << 25U); 296 | } 297 | } 298 | 299 | OPA_CTL = ctl; 300 | OPA_LPBT = lpbt; 301 | } 302 | 303 | /*! 304 | \brief get OPA calibration flag 305 | \param[in] opa_periph 306 | \arg OPAx(x =0,1,2) 307 | \param[out] none 308 | \retval The state of the OPA calibration flag (SET or RESET) 309 | */ 310 | FlagStatus opa_cal_out_get(uint32_t opa_periph) 311 | { 312 | uint32_t data = 0U; 313 | FlagStatus bitstatus = RESET; 314 | data = OPA_CTL; 315 | 316 | if(OPA0 == opa_periph){ 317 | /* get opa0 calibration output bit status */ 318 | if ((uint32_t)RESET != (data & OPA_CTL_OPA1CALOUT)){ 319 | bitstatus = SET; 320 | }else{ 321 | bitstatus = RESET; 322 | } 323 | }else if(OPA1 == opa_periph){ 324 | /* get opa1 calibration output bit status */ 325 | if ((uint32_t)RESET != (data & OPA_CTL_OPA1CALOUT)){ 326 | bitstatus = SET; 327 | }else{ 328 | bitstatus = RESET; 329 | } 330 | }else{ 331 | /* get opa2 calibration output bit status */ 332 | if((uint32_t)RESET != (data & OPA_CTL_OPA1CALOUT)){ 333 | bitstatus = SET; 334 | }else{ 335 | bitstatus = RESET; 336 | } 337 | } 338 | return bitstatus; 339 | } 340 | 341 | #endif /* GD32F170_190 */ 342 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/gd32f1x0_pmu.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file gd32f1x0_pmu.c 3 | \brief PMU driver 4 | */ 5 | 6 | /* 7 | Copyright (C) 2017 GigaDevice 8 | 9 | 2014-12-26, V1.0.0, platform GD32F1x0(x=3,5) 10 | 2016-01-15, V2.0.0, platform GD32F1x0(x=3,5,7,9) 11 | 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | */ 14 | 15 | #include "gd32f1x0_pmu.h" 16 | 17 | /*! 18 | \brief reset PMU register 19 | \param[in] none 20 | \param[out] none 21 | \retval none 22 | */ 23 | void pmu_deinit(void) 24 | { 25 | /* reset PMU */ 26 | rcu_periph_reset_enable(RCU_PMURST); 27 | rcu_periph_reset_disable(RCU_PMURST); 28 | } 29 | 30 | /*! 31 | \brief select low voltage detector threshold 32 | \param[in] lvdt_n: 33 | \arg PMU_LVDT_0: voltage threshold is 2.2V (GD32F130_150) or 2.4V (GD32F170_190) 34 | \arg PMU_LVDT_1: voltage threshold is 2.3V (GD32F130_150) or 2.7V (GD32F170_190) 35 | \arg PMU_LVDT_2: voltage threshold is 2.4V (GD32F130_150) or 3.0V (GD32F170_190) 36 | \arg PMU_LVDT_3: voltage threshold is 2.5V (GD32F130_150) or 3.3V (GD32F170_190) 37 | \arg PMU_LVDT_4: voltage threshold is 2.6V (GD32F130_150) or 3.6V (GD32F170_190) 38 | \arg PMU_LVDT_5: voltage threshold is 2.7V (GD32F130_150) or 3.9V (GD32F170_190) 39 | \arg PMU_LVDT_6: voltage threshold is 2.8V (GD32F130_150) or 4.2V (GD32F170_190) 40 | \arg PMU_LVDT_7: voltage threshold is 2.9V (GD32F130_150) or 4.5V (GD32F170_190) 41 | \param[out] none 42 | \retval none 43 | */ 44 | void pmu_lvd_select(uint32_t lvdt_n) 45 | { 46 | /* disable LVD */ 47 | PMU_CTL &= ~PMU_CTL_LVDEN; 48 | /* clear LVDT bits */ 49 | PMU_CTL &= ~PMU_CTL_LVDT; 50 | /* set LVDT bits according to lvdt_n */ 51 | PMU_CTL |= lvdt_n; 52 | /* enable LVD */ 53 | PMU_CTL |= PMU_CTL_LVDEN; 54 | 55 | } 56 | 57 | /*! 58 | \brief PMU lvd disable 59 | \param[in] none 60 | \param[out] none 61 | \retval none 62 | */ 63 | void pmu_lvd_disable(void) 64 | { 65 | /* disable LVD */ 66 | PMU_CTL &= ~PMU_CTL_LVDEN; 67 | } 68 | 69 | /*! 70 | \brief PMU work at sleep mode 71 | \param[in] sleepmodecmd: 72 | \arg WFI_CMD: use WFI command 73 | \arg WFE_CMD: use WFE command 74 | \param[out] none 75 | \retval none 76 | */ 77 | void pmu_to_sleepmode(uint8_t sleepmodecmd) 78 | { 79 | /* clear sleepdeep bit of Cortex-M3 system control register */ 80 | SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); 81 | 82 | /* select WFI or WFE command to enter sleep mode */ 83 | if(WFI_CMD == sleepmodecmd){ 84 | __WFI(); 85 | }else{ 86 | __WFE(); 87 | } 88 | } 89 | 90 | /*! 91 | \brief PMU work at deepsleep mode 92 | \param[in] ldo 93 | \arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode 94 | \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode 95 | \param[in] deepsleepmodecmd: 96 | \arg WFI_CMD: use WFI command 97 | \arg WFE_CMD: use WFE command 98 | \param[out] none 99 | \retval none 100 | */ 101 | void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) 102 | { 103 | static uint32_t reg_snap[ 4 ]; 104 | /* clear stbmod and ldolp bits */ 105 | PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); 106 | 107 | /* set ldolp bit according to pmu_ldo */ 108 | PMU_CTL |= ldo; 109 | 110 | /* set sleepdeep bit of Cortex-M3 system control register */ 111 | SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 112 | 113 | reg_snap[ 0 ] = REG32( 0xE000E010 ); 114 | reg_snap[ 1 ] = REG32( 0xE000E100 ); 115 | reg_snap[ 2 ] = REG32( 0xE000E104 ); 116 | reg_snap[ 3 ] = REG32( 0xE000E108 ); 117 | 118 | REG32( 0xE000E010 ) &= 0x00010004; 119 | REG32( 0xE000E180 ) = 0XB7FFEF19; 120 | REG32( 0xE000E184 ) = 0XFFFFFBFF; 121 | REG32( 0xE000E188 ) = 0xFFFFFFFF; 122 | 123 | /* select WFI or WFE command to enter deepsleep mode */ 124 | if(WFI_CMD == deepsleepmodecmd){ 125 | __WFI(); 126 | }else{ 127 | __SEV(); 128 | __WFE(); 129 | __WFE(); 130 | } 131 | 132 | REG32( 0xE000E010 ) = reg_snap[ 0 ] ; 133 | REG32( 0xE000E100 ) = reg_snap[ 1 ] ; 134 | REG32( 0xE000E104 ) = reg_snap[ 2 ] ; 135 | REG32( 0xE000E108 ) = reg_snap[ 3 ] ; 136 | 137 | /* reset sleepdeep bit of Cortex-M3 system control register */ 138 | SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); 139 | } 140 | 141 | /*! 142 | \brief pmu work at standby mode 143 | \param[in] standbymodecmd: 144 | \arg WFI_CMD: use WFI command 145 | \arg WFE_CMD: use WFE command 146 | \param[out] none 147 | \retval none 148 | */ 149 | void pmu_to_standbymode(uint8_t standbymodecmd) 150 | { 151 | /* set sleepdeep bit of Cortex-M3 system control register */ 152 | SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 153 | 154 | /* set stbmod bit */ 155 | PMU_CTL |= PMU_CTL_STBMOD; 156 | 157 | /* reset wakeup flag */ 158 | PMU_CTL |= PMU_CTL_WURST; 159 | 160 | /* select WFI or WFE command to enter standby mode */ 161 | if(WFI_CMD == standbymodecmd){ 162 | __WFI(); 163 | }else{ 164 | __WFE(); 165 | } 166 | } 167 | 168 | /*! 169 | \brief clear flag bit 170 | \param[in] flag_reset: 171 | \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag 172 | \arg PMU_FLAG_RESET_STANDBY: reset standby flag 173 | \param[out] none 174 | \retval none 175 | */ 176 | void pmu_flag_clear(uint32_t flag_reset) 177 | { 178 | switch(flag_reset){ 179 | case PMU_FLAG_RESET_WAKEUP: 180 | /* reset wakeup flag */ 181 | PMU_CTL |= PMU_CTL_WURST; 182 | break; 183 | case PMU_FLAG_RESET_STANDBY: 184 | /* reset standby flag */ 185 | PMU_CTL |= PMU_CTL_STBRST; 186 | break; 187 | default : 188 | break; 189 | } 190 | } 191 | 192 | /*! 193 | \brief get flag state 194 | \param[in] flag: 195 | \arg PMU_FLAG_WAKEUP: wakeup flag 196 | \arg PMU_FLAG_STANDBY: standby flag 197 | \arg PMU_FLAG_LVD: lvd flag 198 | \param[out] none 199 | \retval FlagStatus SET or RESET 200 | */ 201 | FlagStatus pmu_flag_get(uint32_t flag ) 202 | { 203 | if(PMU_CS & flag){ 204 | return SET; 205 | }else{ 206 | return RESET; 207 | } 208 | } 209 | 210 | /*! 211 | \brief backup domain write enable 212 | \param[in] none 213 | \param[out] none 214 | \retval none 215 | */ 216 | void pmu_backup_write_enable(void) 217 | { 218 | PMU_CTL |= PMU_CTL_BKPWEN; 219 | } 220 | 221 | /*! 222 | \brief backup domain write disable 223 | \param[in] none 224 | \param[out] none 225 | \retval none 226 | */ 227 | void pmu_backup_write_disable(void) 228 | { 229 | PMU_CTL &= ~PMU_CTL_BKPWEN; 230 | } 231 | 232 | /*! 233 | \brief wakeup pin enable 234 | \param[in] wakeup_pin: 235 | \arg PMU_WAKEUP_PIN0: wakeup pin 0 236 | \arg PMU_WAKEUP_PIN1: wakeup pin 1 237 | \param[out] none 238 | \retval none 239 | */ 240 | void pmu_wakeup_pin_enable(uint32_t wakeup_pin ) 241 | { 242 | PMU_CS |= wakeup_pin; 243 | } 244 | 245 | /*! 246 | \brief wakeup pin disable 247 | \param[in] wakeup_pin: 248 | \arg PMU_WAKEUP_PIN0: wakeup pin 0 249 | \arg PMU_WAKEUP_PIN1: wakeup pin 1 250 | \param[out] none 251 | \retval none 252 | */ 253 | void pmu_wakeup_pin_disable(uint32_t wakeup_pin ) 254 | { 255 | PMU_CS &= ~wakeup_pin; 256 | 257 | } 258 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/gd32f1x0_syscfg.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file gd32f1x0_syscfg.c 3 | \brief SYSCFG driver 4 | */ 5 | 6 | /* 7 | Copyright (C) 2017 GigaDevice 8 | 9 | 2014-12-26, V1.0.0, platform GD32F1x0(x=3,5) 10 | 2016-01-15, V2.0.0, platform GD32F1x0(x=3,5,7,9) 11 | 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | */ 14 | 15 | #include "gd32f1x0_syscfg.h" 16 | 17 | /*! 18 | \brief reset the SYSCFG registers 19 | \param[in] none 20 | \param[out] none 21 | \retval none 22 | */ 23 | void syscfg_deinit(void) 24 | { 25 | rcu_periph_reset_enable(RCU_CFGCMPRST); 26 | rcu_periph_reset_disable(RCU_CFGCMPRST); 27 | } 28 | 29 | /*! 30 | \brief enable the DMA channels remapping 31 | \param[in] syscfg_dma_remap: specify the DMA channels to remap 32 | \arg SYSCFG_DMA_REMAP_TIMER16: remap TIMER16 channel0 and UP DMA requests to channel1(defaut channel0) 33 | \arg SYSCFG_DMA_REMAP_TIMER15: remap TIMER15 channel2 and UP DMA requests to channel3(defaut channel2) 34 | \arg SYSCFG_DMA_REMAP_USART0RX: remap USART0 Rx DMA request to channel4(default channel2) 35 | \arg SYSCFG_DMA_REMAP_USART0TX: remap USART0 Tx DMA request to channel3(default channel1) 36 | \arg SYSCFG_DMA_REMAP_ADC: remap ADC DMA requests from channel0 to channel1 37 | \param[out] none 38 | \retval none 39 | */ 40 | void syscfg_dma_remap_enable(uint32_t syscfg_dma_remap) 41 | { 42 | SYSCFG_CFG0 |= syscfg_dma_remap; 43 | } 44 | 45 | /*! 46 | \brief disable the DMA channels remapping 47 | \param[in] syscfg_dma_remap: specify the DMA channels to remap 48 | \arg SYSCFG_DMA_REMAP_TIMER16: remap TIMER16 channel0 and UP DMA requests to channel1(defaut channel0) 49 | \arg SYSCFG_DMA_REMAP_TIMER15: remap TIMER15 channel2 and UP DMA requests to channel3(defaut channel2) 50 | \arg SYSCFG_DMA_REMAP_USART0RX: remap USART0 Rx DMA request to channel4(default channel2) 51 | \arg SYSCFG_DMA_REMAP_USART0TX: remap USART0 Tx DMA request to channel3(default channel1) 52 | \arg SYSCFG_DMA_REMAP_ADC: remap ADC DMA requests from channel0 to channel1 53 | \param[out] none 54 | \retval none 55 | */ 56 | void syscfg_dma_remap_disable(uint32_t syscfg_dma_remap) 57 | { 58 | SYSCFG_CFG0 &= ~syscfg_dma_remap; 59 | } 60 | 61 | /*! 62 | \brief enable PB9 high current capability 63 | \param[in] none 64 | \param[out] none 65 | \retval none 66 | */ 67 | void syscfg_high_current_enable(void) 68 | { 69 | SYSCFG_CFG0 |= SYSCFG_HIGH_CURRENT_ENABLE; 70 | } 71 | 72 | /*! 73 | \brief disable PB9 high current capability 74 | \param[in] none 75 | \param[out] none 76 | \retval none 77 | */ 78 | void syscfg_high_current_disable(void) 79 | { 80 | SYSCFG_CFG0 &= SYSCFG_HIGH_CURRENT_DISABLE; 81 | } 82 | 83 | #ifdef GD32F170_190 84 | /*! 85 | \brief configure the VLCD intermediate voltage rail 86 | \param[in] vlcd_bias: specify VLCD bias 87 | \arg VLCD_BIAS1_2_RAIL1: VLCD bias is 1/2, using rail1 88 | \arg VLCD_BIAS1_2_RAIL2: VLCD bias is 1/2, using rail2 89 | \arg VLCD_BIAS1_2_RAIL3: VLCD bias is 1/2, using rail3 90 | \arg VLCD_BIAS1_3_RAIL1_2: VLCD bias is 1/3, using rail1 and rail2 91 | \arg VLCD_BIAS1_3_RAIL1_3: VLCD bias is 1/3, using rail1 and rail3 92 | \arg VLCD_BIAS1_4_RAILALL: VLCD bias is 1/4, using all rails 93 | \param[out] none 94 | \retval none 95 | */ 96 | void syscfg_vlcd_rail_config(uint8_t vlcd_bias) 97 | { 98 | uint32_t cfg1 = SYSCFG_CFG1; 99 | 100 | /* Clear system configuration register 1 */ 101 | SYSCFG_CFG1 = 0U; 102 | 103 | switch(vlcd_bias){ 104 | /* according to VLCD bias, configure rails combination */ 105 | case VLCD_BIAS1_2_RAIL1: 106 | SYSCFG_CFG1 |= SYSCFG_VLCD_RAIL1; 107 | break; 108 | case VLCD_BIAS1_2_RAIL2: 109 | SYSCFG_CFG1 |= SYSCFG_VLCD_RAIL2; 110 | break; 111 | case VLCD_BIAS1_2_RAIL3: 112 | SYSCFG_CFG1 |= SYSCFG_VLCD_RAIL3; 113 | break; 114 | case VLCD_BIAS1_3_RAIL1_2: 115 | SYSCFG_CFG1 |= SYSCFG_VLCD_RAIL2 | SYSCFG_VLCD_RAIL1; 116 | break; 117 | case VLCD_BIAS1_3_RAIL1_3: 118 | SYSCFG_CFG1 |= SYSCFG_VLCD_RAIL3 | SYSCFG_VLCD_RAIL1; 119 | break; 120 | case VLCD_BIAS1_4_RAILALL: 121 | SYSCFG_CFG1 |= SYSCFG_VLCD_RAIL3 | SYSCFG_VLCD_RAIL2 | SYSCFG_VLCD_RAIL1; 122 | break; 123 | default: 124 | SYSCFG_CFG1 = cfg1; 125 | break; 126 | } 127 | } 128 | #endif /* GD32F170_190 */ 129 | 130 | /*! 131 | \brief configure the GPIO pin as EXTI Line 132 | \param[in] exti_port: specify the GPIO port used in EXTI 133 | \arg EXTI_SOURCE_GPIOx(x = A,B,C,D,F): EXTI GPIO port 134 | \param[in] exti_pin: specify the EXTI line 135 | \arg EXTI_SOURCE_PINx(x = 0..15): EXTI GPIO pin 136 | \param[out] none 137 | \retval none 138 | */ 139 | void syscfg_exti_line_config(uint8_t exti_port, uint8_t exti_pin) 140 | { 141 | uint32_t clear_exti_mask = ~((uint32_t)EXTI_SS_MASK << (EXTI_SS_MSTEP(exti_pin))); 142 | uint32_t config_exti_mask = ((uint32_t)exti_port) << (EXTI_SS_MSTEP(exti_pin)); 143 | 144 | switch(exti_pin / EXTI_SS_JSTEP){ 145 | case EXTISS0: 146 | /* clear EXTI source line(0..3) */ 147 | SYSCFG_EXTISS0 &= clear_exti_mask; 148 | /* configure EXTI soure line(0..3) */ 149 | SYSCFG_EXTISS0 |= config_exti_mask; 150 | break; 151 | case EXTISS1: 152 | /* clear EXTI soure line(4..7) */ 153 | SYSCFG_EXTISS1 &= clear_exti_mask; 154 | /* configure EXTI soure line(4..7) */ 155 | SYSCFG_EXTISS1 |= config_exti_mask; 156 | break; 157 | case EXTISS2: 158 | /* clear EXTI soure line(8..11) */ 159 | SYSCFG_EXTISS2 &= clear_exti_mask; 160 | /* configure EXTI soure line(8..11) */ 161 | SYSCFG_EXTISS2 |= config_exti_mask; 162 | break; 163 | case EXTISS3: 164 | /* clear EXTI soure line(12..15) */ 165 | SYSCFG_EXTISS3 &= clear_exti_mask; 166 | /* configure EXTI soure line(12..15) */ 167 | SYSCFG_EXTISS3 |= config_exti_mask; 168 | break; 169 | default: 170 | break; 171 | } 172 | } 173 | 174 | /*! 175 | \brief connect TIMER0/14/15/16 break input to the selected parameter 176 | \param[in] syscfg_lock: Specify the parameter to be connected 177 | \arg SYSCFG_LOCK_LOCKUP: Cortex-M3 lockup output connected to the break input 178 | \arg SYSCFG_LOCK_SRAM_PARITY_ERROR: SRAM_PARITY check error connected to the break input 179 | \arg SYSCFG_LOCK_LVD: LVD interrupt connected to the break input 180 | \param[out] none 181 | \retval none 182 | */ 183 | void syscfg_lock_config(uint32_t syscfg_lock) 184 | { 185 | SYSCFG_CFG2 |= syscfg_lock; 186 | } 187 | 188 | /*! 189 | \brief check if the specified flag in SYSCFG_CFG2 is set or not. 190 | \param[in] syscfg_flag: specify the flag in SYSCFG_CFG2 to check. 191 | \arg SYSCFG_SRAM_PCEF: SRAM parity check error flag. 192 | \param[out] none 193 | \retval the syscfg_flag state returned (SET or RESET). 194 | */ 195 | FlagStatus syscfg_flag_get(uint32_t syscfg_flag) 196 | { 197 | if((SYSCFG_CFG2 & syscfg_flag) != (uint32_t)RESET){ 198 | return SET; 199 | }else{ 200 | return RESET; 201 | } 202 | } 203 | 204 | /*! 205 | \brief clear the flag in SYSCFG_CFG2 by writing 1. 206 | \param[in] syscfg_flag: Specify the flag in SYSCFG_CFG2 to clear. 207 | \arg SYSCFG_SRAM_PCEF: SRAM parity check error flag. 208 | \param[out] none 209 | \retval none 210 | */ 211 | void syscfg_flag_clear(uint32_t syscfg_flag) 212 | { 213 | SYSCFG_CFG2 |= (uint32_t) syscfg_flag; 214 | } 215 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/gd32f1x0_wwdgt.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file gd32f1x0_wwdgt.c 3 | \brief WWDGT driver 4 | */ 5 | 6 | /* 7 | Copyright (C) 2017 GigaDevice 8 | 9 | 2014-12-26, V1.0.0, platform GD32F1x0(x=3,5) 10 | 2016-01-15, V2.0.0, platform GD32F1x0(x=3,5,7,9) 11 | 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | */ 14 | 15 | #include "gd32f1x0_wwdgt.h" 16 | #include "gd32f1x0_rcu.h" 17 | 18 | /*! 19 | \brief reset the window watchdog timer configuration 20 | \param[in] none 21 | \param[out] none 22 | \retval none 23 | */ 24 | void wwdgt_deinit(void) 25 | { 26 | rcu_periph_reset_enable(RCU_WWDGTRST); 27 | rcu_periph_reset_disable(RCU_WWDGTRST); 28 | } 29 | 30 | /*! 31 | \brief configure the window watchdog timer counter value 32 | \param[in] counter_value: 0x00 - 0x7F 33 | \param[out] none 34 | \retval none 35 | */ 36 | void wwdgt_counter_update(uint16_t counter_value) 37 | { 38 | uint32_t reg = 0U; 39 | 40 | reg = WWDGT_CTL & (~WWDGT_CTL_CNT); 41 | reg |= (uint32_t)(CTL_CNT((uint32_t)counter_value)); 42 | 43 | WWDGT_CTL = (uint32_t)reg; 44 | } 45 | 46 | /*! 47 | \brief start the window watchdog timer counter 48 | \param[in] none 49 | \param[out] none 50 | \retval none 51 | */ 52 | void wwdgt_enable(void) 53 | { 54 | WWDGT_CTL |= WWDGT_CTL_WDGTEN; 55 | } 56 | 57 | /*! 58 | \brief configure counter value, window value, and prescaler divider value 59 | \param[in] counter: 0x00 - 0x7F 60 | \param[in] window: 0x00 - 0x7F 61 | \param[in] prescaler: wwdgt prescaler value 62 | \arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1 63 | \arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2 64 | \arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4 65 | \arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8 66 | \param[out] none 67 | \retval none 68 | */ 69 | void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler) 70 | { 71 | uint32_t reg_cfg = 0U, reg_ctl = 0U; 72 | 73 | /* clear WIN and PSC bits, clear CNT bit */ 74 | reg_cfg = WWDGT_CFG &(~(WWDGT_CFG_WIN | WWDGT_CFG_PSC)); 75 | reg_ctl = WWDGT_CTL &(~(uint32_t)WWDGT_CTL_CNT); 76 | 77 | /* configure WIN and PSC bits, configure CNT bit */ 78 | reg_cfg |= (uint32_t)(CFG_WIN(window)); 79 | reg_cfg |= (uint32_t)(prescaler); 80 | reg_ctl |= (uint32_t)(CTL_CNT(counter)); 81 | 82 | WWDGT_CFG = (uint32_t)reg_cfg; 83 | WWDGT_CTL = (uint32_t)reg_ctl; 84 | } 85 | 86 | /*! 87 | \brief enable early wakeup interrupt of WWDGT 88 | \param[in] none 89 | \param[out] none 90 | \retval none 91 | */ 92 | void wwdgt_interrupt_enable(void) 93 | { 94 | WWDGT_CFG |= WWDGT_CFG_EWIE; 95 | } 96 | 97 | /*! 98 | \brief check early wakeup interrupt state of WWDGT 99 | \param[in] none 100 | \param[out] none 101 | \retval FlagStatus: SET or RESET 102 | */ 103 | FlagStatus wwdgt_flag_get(void) 104 | { 105 | if(WWDGT_STAT & WWDGT_STAT_EWIF){ 106 | return SET; 107 | } 108 | 109 | return RESET; 110 | } 111 | 112 | /*! 113 | \brief clear early wakeup interrupt state of WWDGT 114 | \param[in] none 115 | \param[out] none 116 | \retval none 117 | */ 118 | void wwdgt_flag_clear(void) 119 | { 120 | WWDGT_STAT &= (uint32_t)(~(uint32_t)WWDGT_STAT_EWIF); 121 | } 122 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/startup_gd32f1x0.s: -------------------------------------------------------------------------------- 1 | ;/*! 2 | ; \file startup_gd32f1x0.s 3 | ; \brief start up file 4 | ;*/ 5 | 6 | ;/* 7 | ; Copyright (C) 2017 GigaDevice 8 | 9 | ; 2014-12-26, V1.0.0, firmware for GD32F1x0(x=3,5) 10 | ; 2016-01-15, V2.0.0, firmware for GD32F1x0(x=3,5,7,9) 11 | ; 2016-04-30, V3.0.0, firmware update for GD32F1x0(x=3,5,7,9) 12 | ; 2017-06-19, V3.1.0, firmware update for GD32F1x0(x=3,5,7,9) 13 | ;*/ 14 | 15 | ; Stack Configuration 16 | ; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> 17 | ; 18 | 19 | Stack_Size EQU 0x00000400 20 | 21 | AREA STACK, NOINIT, READWRITE, ALIGN=3 22 | Stack_Mem SPACE Stack_Size 23 | __initial_sp 24 | 25 | 26 | ; Heap Configuration 27 | ; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> 28 | ; 29 | 30 | Heap_Size EQU 0x00000400 31 | 32 | AREA HEAP, NOINIT, READWRITE, ALIGN=3 33 | __heap_base 34 | Heap_Mem SPACE Heap_Size 35 | __heap_limit 36 | 37 | PRESERVE8 38 | THUMB 39 | 40 | ; /* reset Vector Mapped to at Address 0 */ 41 | AREA RESET, DATA, READONLY 42 | EXPORT __Vectors 43 | EXPORT __Vectors_End 44 | EXPORT __Vectors_Size 45 | 46 | __Vectors DCD __initial_sp ; Top of Stack 47 | DCD Reset_Handler ; Reset Handler 48 | DCD NMI_Handler ; NMI Handler 49 | DCD HardFault_Handler ; Hard Fault Handler 50 | DCD MemManage_Handler ; MPU Fault Handler 51 | DCD BusFault_Handler ; Bus Fault Handler 52 | DCD UsageFault_Handler ; Usage Fault Handler 53 | DCD 0 ; Reserved 54 | DCD 0 ; Reserved 55 | DCD 0 ; Reserved 56 | DCD 0 ; Reserved 57 | DCD SVC_Handler ; SVCall Handler 58 | DCD DebugMon_Handler ; Debug Monitor Handler 59 | DCD 0 ; Reserved 60 | DCD PendSV_Handler ; PendSV Handler 61 | DCD SysTick_Handler ; SysTick Handler 62 | 63 | ; /* external interrupts handler */ 64 | DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer 65 | DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect 66 | DCD RTC_IRQHandler ; 18:RTC through EXTI Line 67 | DCD FMC_IRQHandler ; 19:FMC 68 | DCD RCU_IRQHandler ; 20:RCU 69 | DCD EXTI0_1_IRQHandler ; 21:EXTI Line 0 and EXTI Line 1 70 | DCD EXTI2_3_IRQHandler ; 22:EXTI Line 2 and EXTI Line 3 71 | DCD EXTI4_15_IRQHandler ; 23:EXTI Line 4 to EXTI Line 15 72 | DCD TSI_IRQHandler ; 24:TSI 73 | DCD DMA_Channel0_IRQHandler ; 25:DMA Channel 0 74 | DCD DMA_Channel1_2_IRQHandler ; 26:DMA Channel 1 and DMA Channel 2 75 | DCD DMA_Channel3_4_IRQHandler ; 27:DMA Channel 3 and DMA Channel 4 76 | DCD ADC_CMP_IRQHandler ; 28:ADC and Comparator 0-1 77 | DCD TIMER0_BRK_UP_TRG_COM_IRQHandler ; 29:TIMER0 Break,Update,Trigger and Commutation 78 | DCD TIMER0_Channel_IRQHandler ; 30:TIMER0 Channel 79 | DCD TIMER1_IRQHandler ; 31:TIMER1 80 | DCD TIMER2_IRQHandler ; 32:TIMER2 81 | DCD TIMER5_DAC_IRQHandler ; 33:TIMER5 and DAC 82 | DCD 0 ; Reserved 83 | DCD TIMER13_IRQHandler ; 35:TIMER13 84 | DCD TIMER14_IRQHandler ; 36:TIMER14 85 | DCD TIMER15_IRQHandler ; 37:TIMER15 86 | DCD TIMER16_IRQHandler ; 38:TIMER16 87 | DCD I2C0_EV_IRQHandler ; 39:I2C0 Event 88 | DCD I2C1_EV_IRQHandler ; 40:I2C1 Event 89 | DCD SPI0_IRQHandler ; 41:SPI0 90 | DCD SPI1_IRQHandler ; 42:SPI1 91 | DCD USART0_IRQHandler ; 43:USART0 92 | DCD USART1_IRQHandler ; 44:USART1 93 | DCD 0 ; Reserved 94 | DCD CEC_IRQHandler ; 46:CEC 95 | DCD 0 ; Reserved 96 | DCD I2C0_ER_IRQHandler ; 48:I2C0 Error 97 | DCD 0 ; Reserved 98 | DCD I2C1_ER_IRQHandler ; 50:I2C1 Error 99 | DCD I2C2_EV_IRQHandler ; 51:I2C2 Event 100 | DCD I2C2_ER_IRQHandler ; 52:I2C2 Error 101 | DCD USBD_LP_IRQHandler ; 53:USBD LP 102 | DCD USBD_HP_IRQHandler ; 54:USBD HP 103 | DCD 0 ; Reserved 104 | DCD 0 ; Reserved 105 | DCD 0 ; Reserved 106 | DCD USBDWakeUp_IRQHandler ; 58:USBD Wakeup 107 | DCD CAN0_TX_IRQHandler ; 59:CAN0 TX 108 | DCD CAN0_RX0_IRQHandler ; 60:CAN0 RX0 109 | DCD CAN0_RX1_IRQHandler ; 61:CAN0 RX1 110 | DCD CAN0_SCE_IRQHandler ; 62:CAN0 SCE 111 | DCD SLCD_IRQHandler ; 63:SLCD 112 | DCD DMA_Channel5_6_IRQHandler ; 64:DMA Channel5 and Channel6 113 | DCD 0 ; Reserved 114 | DCD 0 ; Reserved 115 | DCD SPI2_IRQHandler ; 67:SPI2 116 | DCD 0 ; Reserved 117 | DCD 0 ; Reserved 118 | DCD 0 ; Reserved 119 | DCD 0 ; Reserved 120 | DCD 0 ; Reserved 121 | DCD 0 ; Reserved 122 | DCD 0 ; Reserved 123 | DCD 0 ; Reserved 124 | DCD 0 ; Reserved 125 | DCD 0 ; Reserved 126 | DCD 0 ; Reserved 127 | DCD 0 ; Reserved 128 | DCD 0 ; Reserved 129 | DCD 0 ; Reserved 130 | DCD 0 ; Reserved 131 | DCD 0 ; Reserved 132 | DCD 0 ; Reserved 133 | DCD 0 ; Reserved 134 | DCD CAN1_TX_IRQHandler ; 86:CAN1 TX 135 | DCD CAN1_RX0_IRQHandler ; 87:CAN1 RX0 136 | DCD CAN1_RX1_IRQHandler ; 88:CAN1 RX1 137 | DCD CAN1_SCE_IRQHandler ; 89:CAN1 SCE 138 | __Vectors_End 139 | 140 | __Vectors_Size EQU __Vectors_End - __Vectors 141 | 142 | AREA |.text|, CODE, READONLY 143 | 144 | ;/* reset Handler */ 145 | Reset_Handler PROC 146 | EXPORT Reset_Handler [WEAK] 147 | IMPORT SystemInit 148 | IMPORT __main 149 | LDR R0, =SystemInit 150 | BLX R0 151 | LDR R0, =__main 152 | BX R0 153 | ENDP 154 | 155 | ;/* dummy Exception Handlers */ 156 | NMI_Handler PROC 157 | EXPORT NMI_Handler [WEAK] 158 | B . 159 | ENDP 160 | HardFault_Handler\ 161 | PROC 162 | EXPORT HardFault_Handler [WEAK] 163 | B . 164 | ENDP 165 | MemManage_Handler\ 166 | PROC 167 | EXPORT MemManage_Handler [WEAK] 168 | B . 169 | ENDP 170 | BusFault_Handler\ 171 | PROC 172 | EXPORT BusFault_Handler [WEAK] 173 | B . 174 | ENDP 175 | UsageFault_Handler\ 176 | PROC 177 | EXPORT UsageFault_Handler [WEAK] 178 | B . 179 | ENDP 180 | SVC_Handler PROC 181 | EXPORT SVC_Handler [WEAK] 182 | B . 183 | ENDP 184 | DebugMon_Handler\ 185 | PROC 186 | EXPORT DebugMon_Handler [WEAK] 187 | B . 188 | ENDP 189 | PendSV_Handler\ 190 | PROC 191 | EXPORT PendSV_Handler [WEAK] 192 | B . 193 | ENDP 194 | SysTick_Handler\ 195 | PROC 196 | EXPORT SysTick_Handler [WEAK] 197 | B . 198 | ENDP 199 | 200 | Default_Handler PROC 201 | ; /* external interrupts handler */ 202 | EXPORT WWDGT_IRQHandler [WEAK] 203 | EXPORT LVD_IRQHandler [WEAK] 204 | EXPORT RTC_IRQHandler [WEAK] 205 | EXPORT FMC_IRQHandler [WEAK] 206 | EXPORT RCU_IRQHandler [WEAK] 207 | EXPORT EXTI0_1_IRQHandler [WEAK] 208 | EXPORT EXTI2_3_IRQHandler [WEAK] 209 | EXPORT EXTI4_15_IRQHandler [WEAK] 210 | EXPORT TSI_IRQHandler [WEAK] 211 | EXPORT DMA_Channel0_IRQHandler [WEAK] 212 | EXPORT DMA_Channel1_2_IRQHandler [WEAK] 213 | EXPORT DMA_Channel3_4_IRQHandler [WEAK] 214 | EXPORT ADC_CMP_IRQHandler [WEAK] 215 | EXPORT TIMER0_BRK_UP_TRG_COM_IRQHandler [WEAK] 216 | EXPORT TIMER0_Channel_IRQHandler [WEAK] 217 | EXPORT TIMER1_IRQHandler [WEAK] 218 | EXPORT TIMER2_IRQHandler [WEAK] 219 | EXPORT TIMER5_DAC_IRQHandler [WEAK] 220 | EXPORT TIMER13_IRQHandler [WEAK] 221 | EXPORT TIMER14_IRQHandler [WEAK] 222 | EXPORT TIMER15_IRQHandler [WEAK] 223 | EXPORT TIMER16_IRQHandler [WEAK] 224 | EXPORT I2C0_EV_IRQHandler [WEAK] 225 | EXPORT I2C1_EV_IRQHandler [WEAK] 226 | EXPORT SPI0_IRQHandler [WEAK] 227 | EXPORT SPI1_IRQHandler [WEAK] 228 | EXPORT USART0_IRQHandler [WEAK] 229 | EXPORT USART1_IRQHandler [WEAK] 230 | EXPORT CEC_IRQHandler [WEAK] 231 | EXPORT I2C0_ER_IRQHandler [WEAK] 232 | EXPORT I2C1_ER_IRQHandler [WEAK] 233 | EXPORT I2C2_EV_IRQHandler [WEAK] 234 | EXPORT I2C2_ER_IRQHandler [WEAK] 235 | EXPORT USBD_LP_IRQHandler [WEAK] 236 | EXPORT USBD_HP_IRQHandler [WEAK] 237 | EXPORT USBDWakeUp_IRQHandler [WEAK] 238 | EXPORT CAN0_TX_IRQHandler [WEAK] 239 | EXPORT CAN0_RX0_IRQHandler [WEAK] 240 | EXPORT CAN0_RX1_IRQHandler [WEAK] 241 | EXPORT CAN0_SCE_IRQHandler [WEAK] 242 | EXPORT SLCD_IRQHandler [WEAK] 243 | EXPORT DMA_Channel5_6_IRQHandler [WEAK] 244 | EXPORT SPI2_IRQHandler [WEAK] 245 | EXPORT CAN1_TX_IRQHandler [WEAK] 246 | EXPORT CAN1_RX0_IRQHandler [WEAK] 247 | EXPORT CAN1_RX1_IRQHandler [WEAK] 248 | EXPORT CAN1_SCE_IRQHandler [WEAK] 249 | 250 | ;/* external interrupts handler */ 251 | WWDGT_IRQHandler 252 | LVD_IRQHandler 253 | RTC_IRQHandler 254 | FMC_IRQHandler 255 | RCU_IRQHandler 256 | EXTI0_1_IRQHandler 257 | EXTI2_3_IRQHandler 258 | EXTI4_15_IRQHandler 259 | TSI_IRQHandler 260 | DMA_Channel0_IRQHandler 261 | DMA_Channel1_2_IRQHandler 262 | DMA_Channel3_4_IRQHandler 263 | ADC_CMP_IRQHandler 264 | TIMER0_BRK_UP_TRG_COM_IRQHandler 265 | TIMER0_Channel_IRQHandler 266 | TIMER1_IRQHandler 267 | TIMER2_IRQHandler 268 | TIMER5_DAC_IRQHandler 269 | TIMER13_IRQHandler 270 | TIMER14_IRQHandler 271 | TIMER15_IRQHandler 272 | TIMER16_IRQHandler 273 | I2C0_EV_IRQHandler 274 | I2C1_EV_IRQHandler 275 | SPI0_IRQHandler 276 | SPI1_IRQHandler 277 | USART0_IRQHandler 278 | USART1_IRQHandler 279 | CEC_IRQHandler 280 | I2C0_ER_IRQHandler 281 | I2C1_ER_IRQHandler 282 | I2C2_EV_IRQHandler 283 | I2C2_ER_IRQHandler 284 | USBD_LP_IRQHandler 285 | USBD_HP_IRQHandler 286 | USBDWakeUp_IRQHandler 287 | CAN0_TX_IRQHandler 288 | CAN0_RX0_IRQHandler 289 | CAN0_RX1_IRQHandler 290 | CAN0_SCE_IRQHandler 291 | SLCD_IRQHandler 292 | DMA_Channel5_6_IRQHandler 293 | SPI2_IRQHandler 294 | CAN1_TX_IRQHandler 295 | CAN1_RX0_IRQHandler 296 | CAN1_RX1_IRQHandler 297 | CAN1_SCE_IRQHandler 298 | B . 299 | ENDP 300 | 301 | ALIGN 302 | 303 | ; user Initial Stack & Heap 304 | 305 | IF :DEF:__MICROLIB 306 | 307 | EXPORT __initial_sp 308 | EXPORT __heap_base 309 | EXPORT __heap_limit 310 | 311 | ELSE 312 | 313 | IMPORT __use_two_region_memory 314 | EXPORT __user_initial_stackheap 315 | 316 | __user_initial_stackheap PROC 317 | LDR R0, = Heap_Mem 318 | LDR R1, =(Stack_Mem + Stack_Size) 319 | LDR R2, = (Heap_Mem + Heap_Size) 320 | LDR R3, = Stack_Mem 321 | BX LR 322 | ENDP 323 | 324 | ALIGN 325 | 326 | ENDIF 327 | 328 | END 329 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/Device/GD32F130C8/system_gd32f1x0.c: -------------------------------------------------------------------------------- 1 | /*! 2 | \file system_gd32f1x0.c 3 | \brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File for 4 | GD32F1x0 Device Series 5 | */ 6 | 7 | /* Copyright (c) 2012 ARM LIMITED 8 | 9 | All rights reserved. 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | - Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | - Neither the name of ARM nor the names of its contributors may be used 18 | to endorse or promote products derived from this software without 19 | specific prior written permission. 20 | * 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. 32 | ---------------------------------------------------------------------------*/ 33 | 34 | /* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ 35 | 36 | #include "gd32f1x0.h" 37 | 38 | /* system frequency define */ 39 | #define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ 40 | #define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ 41 | #define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ 42 | 43 | /* select a system clock by uncommenting the following line */ 44 | //#define __SYSTEM_CLOCK_8M_HXTAL (__HXTAL) 45 | //#define __SYSTEM_CLOCK_8M_IRC8M (__IRC8M) 46 | //#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) 47 | #define __SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2 (uint32_t)(72000000) 48 | 49 | #define SEL_IRC8M 0x00 50 | #define SEL_HXTAL 0x01 51 | #define SEL_PLL 0x02 52 | 53 | /* set the system clock frequency and declare the system clock configuration function */ 54 | #ifdef __SYSTEM_CLOCK_8M_HXTAL 55 | uint32_t SystemCoreClock = __SYSTEM_CLOCK_8M_HXTAL; 56 | static void system_clock_8m_hxtal(void); 57 | #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) 58 | uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; 59 | static void system_clock_72m_hxtal(void); 60 | #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2) 61 | uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2; 62 | static void system_clock_72m_irc8m(void); 63 | #else 64 | uint32_t SystemCoreClock = __SYSTEM_CLOCK_8M_IRC8M; 65 | static void system_clock_8m_irc8m(void); 66 | #endif /* __SYSTEM_CLOCK_8M_HXTAL */ 67 | 68 | /* configure the system clock */ 69 | static void system_clock_config(void); 70 | 71 | /*! 72 | \brief setup the microcontroller system, initialize the system 73 | \param[in] none 74 | \param[out] none 75 | \retval none 76 | */ 77 | void SystemInit (void) 78 | { 79 | /* enable IRC8M */ 80 | RCU_CTL0 |= RCU_CTL0_IRC8MEN; 81 | while(0U == (RCU_CTL0 & RCU_CTL0_IRC8MSTB)){ 82 | } 83 | /* reset RCU */ 84 | #ifdef GD32F130_150 85 | RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |\ 86 | RCU_CFG0_ADCPSC | RCU_CFG0_CKOUTSEL | RCU_CFG0_CKOUTDIV | RCU_CFG0_PLLDV); 87 | #elif defined (GD32F170_190) 88 | RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |\ 89 | RCU_CFG0_ADCPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_CKOUT0DIV | RCU_CFG0_PLLDV); 90 | #endif /* GD32F130_150 */ 91 | RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLDV); 92 | #ifdef GD32F130_150 93 | RCU_CFG0 &= ~(RCU_CFG0_USBDPSC); 94 | #endif /* GD32F130_150 */ 95 | RCU_CTL0 &= ~(RCU_CTL0_HXTALEN | RCU_CTL0_CKMEN | RCU_CTL0_PLLEN | RCU_CTL0_HXTALBPS); 96 | RCU_CFG1 &= ~RCU_CFG1_HXTALPREDV; 97 | RCU_CFG2 &= ~(RCU_CFG2_USART0SEL | RCU_CFG2_CECSEL | RCU_CFG2_ADCSEL); 98 | #ifdef GD32F130_150 99 | RCU_CTL1 &= ~RCU_CTL1_IRC14MEN; 100 | #elif defined (GD32F170_190) 101 | RCU_CFG2 &= ~RCU_CFG2_IRC28MDIV; 102 | RCU_CTL1 &= ~RCU_CTL1_IRC28MEN; 103 | RCU_CFG3 &= ~RCU_CFG3_CKOUT1SRC; 104 | RCU_CFG3 &= ~RCU_CFG3_CKOUT1DIV; 105 | #endif /* GD32F130_150 */ 106 | RCU_INT = 0x00000000U; 107 | 108 | /* configure system clock */ 109 | system_clock_config(); 110 | } 111 | 112 | /*! 113 | \brief configure the system clock 114 | \param[in] none 115 | \param[out] none 116 | \retval none 117 | */ 118 | static void system_clock_config(void) 119 | { 120 | #ifdef __SYSTEM_CLOCK_8M_HXTAL 121 | system_clock_8m_hxtal(); 122 | #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) 123 | system_clock_72m_hxtal(); 124 | #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2) 125 | system_clock_72m_irc8m(); 126 | #else 127 | system_clock_8m_irc8m(); 128 | #endif /* __SYSTEM_CLOCK_8M_HXTAL */ 129 | } 130 | 131 | #ifdef __SYSTEM_CLOCK_8M_HXTAL 132 | /*! 133 | \brief configure the system clock to 8M by HXTAL 134 | \param[in] none 135 | \param[out] none 136 | \retval none 137 | */ 138 | static void system_clock_8m_hxtal(void) 139 | { 140 | uint32_t timeout = 0; 141 | 142 | /* enable HXTAL */ 143 | RCU_CTL0 |= RCU_CTL0_HXTALEN; 144 | 145 | /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ 146 | while((0 == (RCU_CTL0 & RCU_CTL0_HXTALSTB)) && (HXTAL_STARTUP_TIMEOUT != timeout++)); 147 | 148 | /* if fail */ 149 | if(0 == (RCU_CTL0 & RCU_CTL0_HXTALSTB)) 150 | return; 151 | 152 | /* HXTAL is stable */ 153 | /* AHB = SYSCLK */ 154 | RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; 155 | /* APB2 = AHB */ 156 | RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; 157 | /* APB1 = AHB */ 158 | RCU_CFG0 |= RCU_APB1_CKAHB_DIV1; 159 | 160 | /* select HXTAL as system clock */ 161 | RCU_CFG0 &= ~RCU_CFG0_SCS; 162 | RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; 163 | 164 | /* wait until HXTAL is selected as system clock */ 165 | while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)); 166 | } 167 | 168 | #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) 169 | /*! 170 | \brief configure the system clock to 72M by PLL which selects HXTAL as its clock source 171 | \param[in] none 172 | \param[out] none 173 | \retval none 174 | */ 175 | static void system_clock_72m_hxtal(void) 176 | { 177 | uint32_t timeout = 0U; 178 | uint32_t stab_flag = 0U; 179 | 180 | /* enable HXTAL */ 181 | RCU_CTL0 |= RCU_CTL0_HXTALEN; 182 | 183 | /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ 184 | do{ 185 | timeout++; 186 | stab_flag = (RCU_CTL0 & RCU_CTL0_HXTALSTB); 187 | } 188 | while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); 189 | 190 | /* if fail */ 191 | if(0U == (RCU_CTL0 & RCU_CTL0_HXTALSTB)){ 192 | return; 193 | } 194 | 195 | /* HXTAL is stable */ 196 | /* AHB = SYSCLK */ 197 | RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; 198 | /* APB2 = AHB */ 199 | RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; 200 | /* APB1 = AHB */ 201 | RCU_CFG0 |= RCU_APB1_CKAHB_DIV1; 202 | 203 | /* PLL = HXTAL * 9 = 72 MHz */ 204 | RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLDV); 205 | RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); 206 | 207 | /* enable PLL */ 208 | RCU_CTL0 |= RCU_CTL0_PLLEN; 209 | 210 | /* wait until PLL is stable */ 211 | while(0U == (RCU_CTL0 & RCU_CTL0_PLLSTB)){ 212 | } 213 | 214 | /* select PLL as system clock */ 215 | RCU_CFG0 &= ~RCU_CFG0_SCS; 216 | RCU_CFG0 |= RCU_CKSYSSRC_PLL; 217 | 218 | /* wait until PLL is selected as system clock */ 219 | while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ 220 | } 221 | } 222 | 223 | #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2) 224 | /*! 225 | \brief configure the system clock to 72M by PLL which selects IRC8M/2 as its clock source 226 | \param[in] none 227 | \param[out] none 228 | \retval none 229 | */ 230 | static void system_clock_72m_irc8m(void) 231 | { 232 | /* AHB = SYSCLK */ 233 | RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; 234 | /* APB2 = AHB */ 235 | RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; 236 | /* APB1 = AHB */ 237 | RCU_CFG0 |= RCU_APB1_CKAHB_DIV1; 238 | /* PLL = (IRC8M/2) * 18 = 72 MHz */ 239 | RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF); 240 | RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL18); 241 | 242 | /* enable PLL */ 243 | RCU_CTL0 |= RCU_CTL0_PLLEN; 244 | 245 | /* wait until PLL is stable */ 246 | while(0 == (RCU_CTL0 & RCU_CTL0_PLLSTB)); 247 | 248 | /* select PLL as system clock */ 249 | RCU_CFG0 &= ~RCU_CFG0_SCS; 250 | RCU_CFG0 |= RCU_CKSYSSRC_PLL; 251 | 252 | /* wait until PLL is selected as system clock */ 253 | while(0 == (RCU_CFG0 & RCU_SCSS_PLL)); 254 | } 255 | 256 | #else 257 | /*! 258 | \brief configure the system clock to 8M by IRC8M 259 | \param[in] none 260 | \param[out] none 261 | \retval none 262 | */ 263 | static void system_clock_8m_irc8m(void) 264 | { 265 | /* AHB = SYSCLK */ 266 | RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; 267 | /* APB2 = AHB */ 268 | RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; 269 | /* APB1 = AHB */ 270 | RCU_CFG0 |= RCU_APB1_CKAHB_DIV1; 271 | 272 | /* select IRC8M as system clock */ 273 | RCU_CFG0 &= ~RCU_CFG0_SCS; 274 | RCU_CFG0 |= RCU_CKSYSSRC_IRC8M; 275 | 276 | /* wait until IRC8M is selected as system clock */ 277 | while(0 != (RCU_CFG0 & RCU_SCSS_IRC8M)); 278 | } 279 | #endif /* __SYSTEM_CLOCK_8M_HXTAL */ 280 | 281 | /*! 282 | \brief update the SystemCoreClock with current core clock retrieved from cpu registers 283 | \param[in] none 284 | \param[out] none 285 | \retval none 286 | */ 287 | void SystemCoreClockUpdate (void) 288 | { 289 | uint32_t sws = 0U; 290 | uint32_t pllmf = 0U, pllmf4 = 0U, pllsel = 0U, prediv = 0U, idx = 0U, clk_exp = 0U; 291 | /* exponent of AHB clock divider */ 292 | const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; 293 | 294 | sws = GET_BITS(RCU_CFG0, 2, 3); 295 | switch(sws){ 296 | /* IRC8M is selected as CK_SYS */ 297 | case SEL_IRC8M: 298 | SystemCoreClock = IRC8M_VALUE; 299 | break; 300 | /* HXTAL is selected as CK_SYS */ 301 | case SEL_HXTAL: 302 | SystemCoreClock = HXTAL_VALUE; 303 | break; 304 | /* PLL is selected as CK_SYS */ 305 | case SEL_PLL: 306 | /* get the value of PLLMF[3:0] */ 307 | pllmf = GET_BITS(RCU_CFG0, 18, 21); 308 | pllmf4 = GET_BITS(RCU_CFG0, 27, 27); 309 | /* high 16 bits */ 310 | if(1U == pllmf4){ 311 | pllmf += 17U; 312 | }else{ 313 | pllmf += 2U; 314 | } 315 | /* PLL clock source selection, HXTAL or IRC8M/2 */ 316 | pllsel = GET_BITS(RCU_CFG0, 16, 16); 317 | if(0U != pllsel){ 318 | prediv = (GET_BITS(RCU_CFG1, 0, 3) + 1U); 319 | SystemCoreClock = (HXTAL_VALUE / prediv) * pllmf; 320 | }else{ 321 | SystemCoreClock = (IRC8M_VALUE >> 1) * pllmf; 322 | } 323 | break; 324 | /* IRC8M is selected as CK_SYS */ 325 | default: 326 | SystemCoreClock = IRC8M_VALUE; 327 | break; 328 | } 329 | /* calculate AHB clock frequency */ 330 | idx = GET_BITS(RCU_CFG0, 4, 7); 331 | clk_exp = ahb_exp[idx]; 332 | SystemCoreClock >>= clk_exp; 333 | } 334 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/RTE/_Target_1/RTE_Components.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Auto generated Run-Time-Environment Component Configuration File 4 | * *** Do not modify ! *** 5 | * 6 | * Project: 'Hoverboard' 7 | * Target: 'Target 1' 8 | */ 9 | 10 | #ifndef RTE_COMPONENTS_H 11 | #define RTE_COMPONENTS_H 12 | 13 | 14 | /* 15 | * Define the Device Header File: 16 | */ 17 | #define CMSIS_device_header "gd32f1x0.h" 18 | 19 | #define RTE_DEVICE_STDPERIPHERALS_ADC 20 | #define RTE_DEVICE_STDPERIPHERALS_DBG 21 | #define RTE_DEVICE_STDPERIPHERALS_DMA 22 | #define RTE_DEVICE_STDPERIPHERALS_FWDGT 23 | #define RTE_DEVICE_STDPERIPHERALS_GPIO 24 | #define RTE_DEVICE_STDPERIPHERALS_I2C 25 | #define RTE_DEVICE_STDPERIPHERALS_MISC 26 | #define RTE_DEVICE_STDPERIPHERALS_OPA 27 | #define RTE_DEVICE_STDPERIPHERALS_PMU 28 | #define RTE_DEVICE_STDPERIPHERALS_RCU 29 | #define RTE_DEVICE_STDPERIPHERALS_SYSCFG 30 | #define RTE_DEVICE_STDPERIPHERALS_TIMER 31 | #define RTE_DEVICE_STDPERIPHERALS_USART 32 | #define RTE_DEVICE_STDPERIPHERALS_WWDGT 33 | 34 | #endif /* RTE_COMPONENTS_H */ 35 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Src/bldc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "gd32f1x0.h" 32 | #include "../Inc/setup.h" 33 | #include "../Inc/defines.h" 34 | #include "../Inc/config.h" 35 | 36 | // Internal constants 37 | const int16_t pwm_res = 72000000 / 2 / PWM_FREQ; // = 2000 38 | 39 | // Global variables for voltage and current 40 | float batteryVoltage = 40.0; 41 | float currentDC = 0.0; 42 | float realSpeed = 0.0; 43 | 44 | // Timeoutvariable set by timeout timer 45 | extern FlagStatus timedOut; 46 | 47 | // Variables to be set from the main routine 48 | int16_t bldc_inputFilterPwm = 0; 49 | FlagStatus bldc_enable = RESET; 50 | 51 | // ADC buffer to be filled by DMA 52 | adc_buf_t adc_buffer; 53 | 54 | // Internal calculation variables 55 | uint8_t hall_a; 56 | uint8_t hall_b; 57 | uint8_t hall_c; 58 | uint8_t hall; 59 | uint8_t pos; 60 | uint8_t lastPos; 61 | int16_t bldc_outputFilterPwm = 0; 62 | int32_t filter_reg; 63 | FlagStatus buzzerToggle = RESET; 64 | uint8_t buzzerFreq = 0; 65 | uint8_t buzzerPattern = 0; 66 | uint16_t buzzerTimer = 0; 67 | int16_t offsetcount = 0; 68 | int16_t offsetdc = 2000; 69 | uint32_t speedCounter = 0; 70 | 71 | //---------------------------------------------------------------------------- 72 | // Commutation table 73 | //---------------------------------------------------------------------------- 74 | const uint8_t hall_to_pos[8] = 75 | { 76 | // annotation: for example SA=0 means hall sensor pulls SA down to Ground 77 | 0, // hall position [-] - No function (access from 1-6) 78 | 3, // hall position [1] (SA=1, SB=0, SC=0) -> PWM-position 3 79 | 5, // hall position [2] (SA=0, SB=1, SC=0) -> PWM-position 5 80 | 4, // hall position [3] (SA=1, SB=1, SC=0) -> PWM-position 4 81 | 1, // hall position [4] (SA=0, SB=0, SC=1) -> PWM-position 1 82 | 2, // hall position [5] (SA=1, SB=0, SC=1) -> PWM-position 2 83 | 6, // hall position [6] (SA=0, SB=1, SC=1) -> PWM-position 6 84 | 0, // hall position [-] - No function (access from 1-6) 85 | }; 86 | 87 | //---------------------------------------------------------------------------- 88 | // Block PWM calculation based on position 89 | //---------------------------------------------------------------------------- 90 | __INLINE void blockPWM(int pwm, int pwmPos, int *y, int *b, int *g) 91 | { 92 | switch(pwmPos) 93 | { 94 | case 1: 95 | *y = 0; 96 | *b = pwm; 97 | *g = -pwm; 98 | break; 99 | case 2: 100 | *y = -pwm; 101 | *b = pwm; 102 | *g = 0; 103 | break; 104 | case 3: 105 | *y = -pwm; 106 | *b = 0; 107 | *g = pwm; 108 | break; 109 | case 4: 110 | *y = 0; 111 | *b = -pwm; 112 | *g = pwm; 113 | break; 114 | case 5: 115 | *y = pwm; 116 | *b = -pwm; 117 | *g = 0; 118 | break; 119 | case 6: 120 | *y = pwm; 121 | *b = 0; 122 | *g = -pwm; 123 | break; 124 | default: 125 | *y = 0; 126 | *b = 0; 127 | *g = 0; 128 | } 129 | } 130 | 131 | //---------------------------------------------------------------------------- 132 | // Set motor enable 133 | //---------------------------------------------------------------------------- 134 | void SetEnable(FlagStatus setEnable) 135 | { 136 | bldc_enable = setEnable; 137 | } 138 | 139 | //---------------------------------------------------------------------------- 140 | // Set pwm -1000 to 1000 141 | //---------------------------------------------------------------------------- 142 | void SetPWM(int16_t setPwm) 143 | { 144 | bldc_inputFilterPwm = CLAMP(setPwm, -1000, 1000); 145 | } 146 | 147 | //---------------------------------------------------------------------------- 148 | // Calculation-Routine for BLDC => calculates with 16kHz 149 | //---------------------------------------------------------------------------- 150 | void CalculateBLDC(void) 151 | { 152 | int y = 0; // yellow = phase A 153 | int b = 0; // blue = phase B 154 | int g = 0; // green = phase C 155 | 156 | // Calibrate ADC offsets for the first 1000 cycles 157 | if (offsetcount < 1000) 158 | { 159 | offsetcount++; 160 | offsetdc = (adc_buffer.current_dc + offsetdc) / 2; 161 | return; 162 | } 163 | 164 | // Calculate battery voltage every 100 cycles 165 | if (buzzerTimer % 100 == 0) 166 | { 167 | batteryVoltage = batteryVoltage * 0.999 + ((float)adc_buffer.v_batt * ADC_BATTERY_VOLT) * 0.001; 168 | } 169 | 170 | #ifdef MASTER 171 | // Create square wave for buzzer 172 | buzzerTimer++; 173 | if (buzzerFreq != 0 && (buzzerTimer / 5000) % (buzzerPattern + 1) == 0) 174 | { 175 | if (buzzerTimer % buzzerFreq == 0) 176 | { 177 | buzzerToggle = buzzerToggle == RESET ? SET : RESET; // toggle variable 178 | gpio_bit_write(BUZZER_PORT, BUZZER_PIN, buzzerToggle); 179 | } 180 | } 181 | else 182 | { 183 | gpio_bit_write(BUZZER_PORT, BUZZER_PIN, RESET); 184 | } 185 | #endif 186 | 187 | // Calculate current DC 188 | currentDC = ABS((adc_buffer.current_dc - offsetdc) * MOTOR_AMP_CONV_DC_AMP); 189 | 190 | // Disable PWM when current limit is reached (current chopping), enable is not set or timeout is reached 191 | if (currentDC > DC_CUR_LIMIT || bldc_enable == RESET || timedOut == SET) 192 | { 193 | timer_automatic_output_disable(TIMER_BLDC); 194 | } 195 | else 196 | { 197 | timer_automatic_output_enable(TIMER_BLDC); 198 | } 199 | 200 | // Read hall sensors 201 | hall_a = gpio_input_bit_get(HALL_A_PORT, HALL_A_PIN); 202 | hall_b = gpio_input_bit_get(HALL_B_PORT, HALL_B_PIN); 203 | hall_c = gpio_input_bit_get(HALL_C_PORT, HALL_C_PIN); 204 | 205 | // Determine current position based on hall sensors 206 | hall = hall_a * 1 + hall_b * 2 + hall_c * 4; 207 | pos = hall_to_pos[hall]; 208 | 209 | // Calculate low-pass filter for pwm value 210 | filter_reg = filter_reg - (filter_reg >> FILTER_SHIFT) + bldc_inputFilterPwm; 211 | bldc_outputFilterPwm = filter_reg >> FILTER_SHIFT; 212 | 213 | // Update PWM channels based on position y(ellow), b(lue), g(reen) 214 | blockPWM(bldc_outputFilterPwm, pos, &y, &b, &g); 215 | 216 | // Set PWM output (pwm_res/2 is the mean value, setvalue has to be between 10 and pwm_res-10) 217 | timer_channel_output_pulse_value_config(TIMER_BLDC, TIMER_BLDC_CHANNEL_G, CLAMP(g + pwm_res / 2, 10, pwm_res-10)); 218 | timer_channel_output_pulse_value_config(TIMER_BLDC, TIMER_BLDC_CHANNEL_B, CLAMP(b + pwm_res / 2, 10, pwm_res-10)); 219 | timer_channel_output_pulse_value_config(TIMER_BLDC, TIMER_BLDC_CHANNEL_Y, CLAMP(y + pwm_res / 2, 10, pwm_res-10)); 220 | 221 | // Increments with 62.5us 222 | if(speedCounter < 4000) // No speed after 250ms 223 | { 224 | speedCounter++; 225 | } 226 | 227 | // Every time position reaches value 1, one round is performed (rising edge) 228 | if (lastPos != 1 && pos == 1) 229 | { 230 | realSpeed = 1991.81f / (float)speedCounter; //[km/h] 231 | speedCounter = 0; 232 | } 233 | else 234 | { 235 | if (speedCounter >= 4000) 236 | { 237 | realSpeed = 0; 238 | } 239 | } 240 | 241 | // Safe last position 242 | lastPos = pos; 243 | } 244 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Src/comms.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "gd32f1x0.h" 32 | 33 | //---------------------------------------------------------------------------- 34 | // Send buffer via USART 35 | //---------------------------------------------------------------------------- 36 | void SendBuffer(uint32_t usart_periph, uint8_t buffer[], uint8_t length) 37 | { 38 | uint8_t index = 0; 39 | 40 | for(; index < length; index++) 41 | { 42 | usart_data_transmit(usart_periph, buffer[index]); 43 | while (usart_flag_get(usart_periph, USART_FLAG_TC) == RESET) {} 44 | } 45 | } 46 | 47 | //---------------------------------------------------------------------------- 48 | // Calculate CRC 49 | //---------------------------------------------------------------------------- 50 | uint16_t CalcCRC(uint8_t *ptr, int count) 51 | { 52 | uint16_t crc; 53 | uint8_t i; 54 | crc = 0; 55 | while (--count >= 0) 56 | { 57 | crc = crc ^ (uint16_t) *ptr++ << 8; 58 | i = 8; 59 | do 60 | { 61 | if (crc & 0x8000) 62 | { 63 | crc = crc << 1 ^ 0x1021; 64 | } 65 | else 66 | { 67 | crc = crc << 1; 68 | } 69 | } while(--i); 70 | } 71 | return (crc); 72 | } 73 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Src/commsBluetooth.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "gd32f1x0.h" 32 | #include "../Inc/defines.h" 33 | #include "../Inc/setup.h" 34 | #include "../Inc/comms.h" 35 | #include "../Inc/commsMasterSlave.h" 36 | #include "../Inc/commsBluetooth.h" 37 | #include "../Inc/led.h" 38 | #include "stdio.h" 39 | #include "string.h" 40 | 41 | // Only slave communicates over bluetooth 42 | #ifdef SLAVE 43 | // Variables which will be send over bluetooth 44 | extern float currentDC; 45 | extern float realSpeed; 46 | 47 | extern uint32_t hornCounter_ms; 48 | 49 | #define USART_BLUETOOTH_TX_BYTES 11 // Transmit byte count including start '/' and stop character '\n' 50 | #define USART_BLUETOOTH_RX_BYTES 11 // Receive byte count including start '/' and stop character '\n' 51 | 52 | extern uint8_t usartSteer_COM_rx_buf[USART_STEER_COM_RX_BUFFERSIZE]; 53 | static uint8_t sBluetoothRecord = 0; 54 | static uint8_t sUSARTBluetoothRecordBuffer[USART_BLUETOOTH_RX_BYTES]; 55 | static uint8_t sUSARTBluetoothRecordBufferCounter = 0; 56 | 57 | void CheckUSARTBluetoothInput(uint8_t USARTBuffer[]); 58 | void SendBluetoothDevice(uint8_t identifier, int16_t value); 59 | 60 | //---------------------------------------------------------------------------- 61 | // Update USART bluetooth input 62 | //---------------------------------------------------------------------------- 63 | void UpdateUSARTBluetoothInput(void) 64 | { 65 | uint8_t character = usartSteer_COM_rx_buf[0]; 66 | 67 | // Start character is captured, start record 68 | if (character == '/') 69 | { 70 | sUSARTBluetoothRecordBufferCounter = 0; 71 | sBluetoothRecord = 1; 72 | } 73 | 74 | if (sBluetoothRecord) 75 | { 76 | sUSARTBluetoothRecordBuffer[sUSARTBluetoothRecordBufferCounter] = character; 77 | sUSARTBluetoothRecordBufferCounter++; 78 | 79 | if (sUSARTBluetoothRecordBufferCounter >= USART_BLUETOOTH_RX_BYTES) 80 | { 81 | sUSARTBluetoothRecordBufferCounter = 0; 82 | sBluetoothRecord = 0; 83 | 84 | // Check input 85 | CheckUSARTBluetoothInput (sUSARTBluetoothRecordBuffer); 86 | } 87 | } 88 | } 89 | 90 | //---------------------------------------------------------------------------- 91 | // Check USART bluetooth input 92 | //---------------------------------------------------------------------------- 93 | void CheckUSARTBluetoothInput(uint8_t USARTBuffer[]) 94 | { 95 | // Auxiliary variables 96 | uint8_t identifier = 0; 97 | uint8_t readWrite = 0; 98 | int16_t sign = 0; 99 | int16_t digit1 = 0; 100 | int16_t digit2 = 0; 101 | int16_t digit3 = 0; 102 | int16_t digit4 = 0; 103 | int16_t digit5 = 0; 104 | int16_t value = 0; 105 | 106 | // Check start and stop character 107 | if ( USARTBuffer[0] != '/' || 108 | USARTBuffer[USART_BLUETOOTH_RX_BYTES - 1] != '\n') 109 | { 110 | return; 111 | } 112 | 113 | // Calculate identifier (number 0-99) 114 | digit1 = (USARTBuffer[1] - '0') * 10; 115 | digit2 = (USARTBuffer[2] - '0'); 116 | identifier = digit1 + digit2; 117 | 118 | // Calculate read or write access (0 - read, 1 - write) 119 | readWrite = USARTBuffer[3] - '0'; 120 | 121 | // If read mode, answer with correct value 122 | if (readWrite == 0) 123 | { 124 | switch(identifier) 125 | { 126 | case 0: 127 | // Answer with battery voltage from master 128 | value = GetBatteryMaster(); 129 | break; 130 | case 1: 131 | // Answer with current from master 132 | value = GetCurrentDCMaster(); 133 | break; 134 | case 2: 135 | // Answer with current from slave 136 | value = currentDC * 100; 137 | break; 138 | case 3: 139 | // Answer with real speed of master 140 | value = GetRealSpeedMaster(); 141 | break; 142 | case 4: 143 | // Answer with real speed of slave 144 | value = realSpeed * 100; 145 | break; 146 | case 5: 147 | // Answer with beeps backwards from master 148 | value = GetBeepsBackwardsMaster() == RESET ? 0 : 1; 149 | break; 150 | case 6: 151 | // Answer with lower LED state of master (music box) 152 | value = GetLowerLEDMaster() == RESET ? 0 : 1; 153 | break; 154 | case 7: 155 | // Answer with upper LED state of master (horn) 156 | value = GetUpperLEDMaster() == RESET ? 0 : 1; 157 | break; 158 | case 8: 159 | // Answer with hue value 160 | value = GetHSBHue(); 161 | break; 162 | case 9: 163 | // Answer with saturation value 164 | value = GetHSBSaturation(); 165 | break; 166 | case 10: 167 | // Answer with brightness value 168 | value = GetHSBBrightness(); 169 | break; 170 | case 11: 171 | // Answer with LEDMode 172 | value = GetRGBProgram(); 173 | break; 174 | case 12: 175 | // Answer with fading speed 176 | value = GetSpeedFading(); 177 | break; 178 | case 13: 179 | // Answer with blink speed 180 | value = GetSpeedBlink(); 181 | break; 182 | case 14: 183 | // Answer with strobe speed 184 | value = GetSpeedStrobe(); 185 | break; 186 | } 187 | 188 | // Send Answer 189 | SendBluetoothDevice(identifier, value); 190 | } 191 | // If write mode, get result value 192 | else if ( readWrite == 1) 193 | { 194 | // Calculate result value (-10000 to 10000) 195 | sign = USARTBuffer[4] == '-' ? -1 : 1; 196 | digit1 = (USARTBuffer[5] - '0') * 10000; 197 | digit2 = (USARTBuffer[6] - '0') * 1000; 198 | digit3 = (USARTBuffer[7] - '0') * 100; 199 | digit4 = (USARTBuffer[8] - '0') * 10; 200 | digit5 = (USARTBuffer[9] - '0'); 201 | value = sign * (digit1 + digit2 + digit3 + digit4 + digit5); 202 | 203 | switch(identifier) 204 | { 205 | case 5: 206 | SetBeepsBackwardsMaster(value == 0 ? RESET : SET); 207 | break; 208 | case 6: 209 | // Set lower LED of master (music box) 210 | SetLowerLEDMaster(value == 0 ? RESET : SET); 211 | break; 212 | case 7: 213 | // Set upper LED of master (horn) 214 | hornCounter_ms = 0; 215 | SetUpperLEDMaster(value == 0 ? RESET : SET); 216 | break; 217 | case 8: 218 | // Set LED hue 219 | SetHSBHue(value); 220 | break; 221 | case 9: 222 | // Set LED saturation 223 | SetHSBSaturation(value); 224 | break; 225 | case 10: 226 | // Set LED brightness 227 | SetHSBBrightness(value); 228 | break; 229 | case 11: 230 | // Set LED mode 231 | SetRGBProgram((LED_PROGRAM)value); 232 | break; 233 | case 12: 234 | // Set fading speed 235 | SetSpeedFading(value); 236 | break; 237 | case 13: 238 | // Set blink speed 239 | SetSpeedBlink(value); 240 | break; 241 | case 14: 242 | // Set strobe speed 243 | SetSpeedStrobe(value); 244 | break; 245 | default: 246 | // Do nothing for the rest of the identifiers 247 | break; 248 | } 249 | } 250 | } 251 | 252 | //---------------------------------------------------------------------------- 253 | // Send frame to bluetooth device 254 | //---------------------------------------------------------------------------- 255 | void SendBluetoothDevice(uint8_t identifier, int16_t value) 256 | { 257 | int index = 0; 258 | char charVal[5]; 259 | uint8_t buffer[USART_BLUETOOTH_TX_BYTES]; 260 | 261 | // Send bluetooth frame 262 | buffer[index++] = '/'; 263 | sprintf(charVal, "%02d", identifier); 264 | buffer[index++] = charVal[0]; 265 | buffer[index++] = charVal[1]; 266 | buffer[index++] = '0'; 267 | sprintf(charVal, "%05d", value); 268 | buffer[index++] = value < 0 ? '-' : '+'; 269 | buffer[index++] = charVal[0]; 270 | buffer[index++] = charVal[1]; 271 | buffer[index++] = charVal[2]; 272 | buffer[index++] = charVal[3]; 273 | buffer[index++] = charVal[4]; 274 | buffer[index++] = '\n'; 275 | 276 | SendBuffer(USART_STEER_COM, buffer, index); 277 | } 278 | 279 | #endif 280 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Src/commsMasterSlave.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "gd32f1x0.h" 32 | #include "../Inc/it.h" 33 | #include "../Inc/comms.h" 34 | #include "../Inc/commsMasterSlave.h" 35 | #include "../Inc/setup.h" 36 | #include "../Inc/config.h" 37 | #include "../Inc/defines.h" 38 | #include "../Inc/bldc.h" 39 | #include "stdio.h" 40 | #include "string.h" 41 | 42 | #ifdef MASTER 43 | #define USART_MASTERSLAVE_TX_BYTES 10 // Transmit byte count including start '/' and stop character '\n' 44 | #define USART_MASTERSLAVE_RX_BYTES 5 // Receive byte count including start '/' and stop character '\n' 45 | 46 | // Variables which will be written by slave frame 47 | extern FlagStatus beepsBackwards; 48 | #endif 49 | #ifdef SLAVE 50 | #define USART_MASTERSLAVE_TX_BYTES 5 // Transmit byte count including start '/' and stop character '\n' 51 | #define USART_MASTERSLAVE_RX_BYTES 10 // Receive byte count including start '/' and stop character '\n' 52 | 53 | // Variables which will be send to master 54 | FlagStatus upperLEDMaster = RESET; 55 | FlagStatus lowerLEDMaster = RESET; 56 | FlagStatus mosfetOutMaster = RESET; 57 | FlagStatus beepsBackwardsMaster = RESET; 58 | 59 | // Variables which will be written by master frame 60 | int16_t currentDCMaster = 0; 61 | int16_t batteryMaster = 0; 62 | int16_t realSpeedMaster = 0; 63 | 64 | void CheckGeneralValue(uint8_t identifier, int16_t value); 65 | #endif 66 | 67 | extern uint8_t usartMasterSlave_rx_buf[USART_MASTERSLAVE_RX_BUFFERSIZE]; 68 | static uint8_t sMasterSlaveRecord = 0; 69 | static uint8_t sUSARTMasterSlaveRecordBuffer[USART_MASTERSLAVE_RX_BYTES]; 70 | static uint8_t sUSARTMasterSlaveRecordBufferCounter = 0; 71 | 72 | void CheckUSARTMasterSlaveInput(uint8_t u8USARTBuffer[]); 73 | void SendBuffer(uint32_t usart_periph, uint8_t buffer[], uint8_t length); 74 | uint16_t CalcCRC(uint8_t *ptr, int count); 75 | 76 | //---------------------------------------------------------------------------- 77 | // Update USART master slave input 78 | //---------------------------------------------------------------------------- 79 | void UpdateUSARTMasterSlaveInput(void) 80 | { 81 | uint8_t character = usartMasterSlave_rx_buf[0]; 82 | 83 | // Start character is captured, start record 84 | if (character == '/') 85 | { 86 | sUSARTMasterSlaveRecordBufferCounter = 0; 87 | sMasterSlaveRecord = 1; 88 | } 89 | 90 | if (sMasterSlaveRecord) 91 | { 92 | sUSARTMasterSlaveRecordBuffer[sUSARTMasterSlaveRecordBufferCounter] = character; 93 | sUSARTMasterSlaveRecordBufferCounter++; 94 | 95 | if (sUSARTMasterSlaveRecordBufferCounter >= USART_MASTERSLAVE_RX_BYTES) 96 | { 97 | sUSARTMasterSlaveRecordBufferCounter = 0; 98 | sMasterSlaveRecord = 0; 99 | 100 | // Check input 101 | CheckUSARTMasterSlaveInput (sUSARTMasterSlaveRecordBuffer); 102 | } 103 | } 104 | } 105 | 106 | //---------------------------------------------------------------------------- 107 | // Check USART master slave input 108 | //---------------------------------------------------------------------------- 109 | void CheckUSARTMasterSlaveInput(uint8_t USARTBuffer[]) 110 | { 111 | #ifdef MASTER 112 | // Result variables 113 | FlagStatus upperLED = RESET; 114 | FlagStatus lowerLED = RESET; 115 | FlagStatus mosfetOut = RESET; 116 | 117 | // Auxiliary variables 118 | uint8_t byte; 119 | #endif 120 | #ifdef SLAVE 121 | // Result variables 122 | int16_t pwmSlave = 0; 123 | FlagStatus enable = RESET; 124 | FlagStatus shutoff = RESET; 125 | FlagStatus chargeStateLowActive = SET; 126 | 127 | // Auxiliary variables 128 | uint8_t identifier = 0; 129 | int16_t value = 0; 130 | uint8_t byte; 131 | #endif 132 | // Auxiliary variables 133 | uint16_t crc; 134 | 135 | // Check start and stop character 136 | if ( USARTBuffer[0] != '/' || 137 | USARTBuffer[USART_MASTERSLAVE_RX_BYTES - 1] != '\n') 138 | { 139 | return; 140 | } 141 | 142 | // Calculate CRC (first bytes except crc and stop byte) 143 | crc = CalcCRC(USARTBuffer, USART_MASTERSLAVE_RX_BYTES - 3); 144 | 145 | // Check CRC 146 | if ( USARTBuffer[USART_MASTERSLAVE_RX_BYTES - 3] != ((crc >> 8) & 0xFF) || 147 | USARTBuffer[USART_MASTERSLAVE_RX_BYTES - 2] != (crc & 0xFF)) 148 | { 149 | return; 150 | } 151 | 152 | #ifdef MASTER 153 | // Calculate setvalues for LED and mosfets 154 | byte = USARTBuffer[1]; 155 | 156 | //none = (byte & BIT(7)) ? SET : RESET; 157 | //none = (byte & BIT(6)) ? SET : RESET; 158 | //none = (byte & BIT(5)) ? SET : RESET; 159 | //none = (byte & BIT(4)) ? SET : RESET; 160 | beepsBackwards = (byte & BIT(3)) ? SET : RESET; 161 | mosfetOut = (byte & BIT(2)) ? SET : RESET; 162 | lowerLED = (byte & BIT(1)) ? SET : RESET; 163 | upperLED = (byte & BIT(0)) ? SET : RESET; 164 | 165 | // Set functions according to the variables 166 | gpio_bit_write(MOSFET_OUT_PORT, MOSFET_OUT_PIN, mosfetOut); 167 | gpio_bit_write(UPPER_LED_PORT, UPPER_LED_PIN, upperLED); 168 | gpio_bit_write(LOWER_LED_PORT, LOWER_LED_PIN, lowerLED); 169 | #endif 170 | #ifdef SLAVE 171 | // Calculate result pwm value -1000 to 1000 172 | pwmSlave = (int16_t)((USARTBuffer[1] << 8) | USARTBuffer[2]); 173 | 174 | // Get identifier 175 | identifier = USARTBuffer[3]; 176 | 177 | // Calculate result general value 178 | value = (int16_t)((USARTBuffer[4] << 8) | USARTBuffer[5]); 179 | 180 | // Calculate setvalues for enable and shutoff 181 | byte = USARTBuffer[6]; 182 | 183 | shutoff = (byte & BIT(7)) ? SET : RESET; 184 | //none = (byte & BIT(6)) ? SET : RESET; 185 | //none = (byte & BIT(5)) ? SET : RESET; 186 | //none = (byte & BIT(4)) ? SET : RESET; 187 | //none = (byte & BIT(3)) ? SET : RESET; 188 | //none = (byte & BIT(2)) ? SET : RESET; 189 | chargeStateLowActive = (byte & BIT(1)) ? SET : RESET; 190 | enable = (byte & BIT(0)) ? SET : RESET; 191 | 192 | if (shutoff == SET) 193 | { 194 | // Disable usart 195 | usart_deinit(USART_MASTERSLAVE); 196 | 197 | // Set pwm and enable to off 198 | SetEnable(RESET); 199 | SetPWM(0); 200 | 201 | gpio_bit_write(SELF_HOLD_PORT, SELF_HOLD_PIN, RESET); 202 | while(1) 203 | { 204 | // Reload watchdog until device is off 205 | fwdgt_counter_reload(); 206 | } 207 | } 208 | 209 | // Set functions according to the variables 210 | gpio_bit_write(LED_GREEN_PORT, LED_GREEN, chargeStateLowActive == SET ? SET : RESET); 211 | gpio_bit_write(LED_RED_PORT, LED_RED, chargeStateLowActive == RESET ? SET : RESET); 212 | SetEnable(enable); 213 | SetPWM(pwmSlave); 214 | CheckGeneralValue(identifier, value); 215 | 216 | // Send answer 217 | SendMaster(upperLEDMaster, lowerLEDMaster, mosfetOutMaster, beepsBackwardsMaster); 218 | 219 | // Reset the pwm timout to avoid stopping motors 220 | ResetTimeout(); 221 | #endif 222 | } 223 | 224 | #ifdef MASTER 225 | //---------------------------------------------------------------------------- 226 | // Send slave frame via USART 227 | //---------------------------------------------------------------------------- 228 | void SendSlave(int16_t pwmSlave, FlagStatus enable, FlagStatus shutoff, FlagStatus chargeState, uint8_t identifier, int16_t value) 229 | { 230 | uint8_t index = 0; 231 | uint16_t crc = 0; 232 | uint8_t buffer[USART_MASTERSLAVE_TX_BYTES]; 233 | 234 | // Format pwmValue and general value 235 | int16_t sendPwm = CLAMP(pwmSlave, -1000, 1000); 236 | uint16_t sendPwm_Uint = (uint16_t)(sendPwm); 237 | uint16_t value_Uint = (uint16_t)(value); 238 | 239 | uint8_t sendByte = 0; 240 | sendByte |= (shutoff << 7); 241 | sendByte |= (0 << 6); 242 | sendByte |= (0 << 5); 243 | sendByte |= (0 << 4); 244 | sendByte |= (0 << 3); 245 | sendByte |= (0 << 2); 246 | sendByte |= (chargeState << 1); 247 | sendByte |= (enable << 0); 248 | 249 | // Send answer 250 | buffer[index++] = '/'; 251 | buffer[index++] = (sendPwm_Uint >> 8) & 0xFF; 252 | buffer[index++] = sendPwm_Uint & 0xFF; 253 | buffer[index++] = identifier; 254 | buffer[index++] = (value_Uint >> 8) & 0xFF; 255 | buffer[index++] = value_Uint & 0xFF; 256 | buffer[index++] = sendByte; 257 | 258 | // Calculate CRC 259 | crc = CalcCRC(buffer, index); 260 | buffer[index++] = (crc >> 8) & 0xFF; 261 | buffer[index++] = crc & 0xFF; 262 | 263 | // Stop byte 264 | buffer[index++] = '\n'; 265 | 266 | SendBuffer(USART_MASTERSLAVE, buffer, index); 267 | } 268 | #endif 269 | #ifdef SLAVE 270 | //---------------------------------------------------------------------------- 271 | // Send master frame via USART 272 | //---------------------------------------------------------------------------- 273 | void SendMaster(FlagStatus upperLEDMaster, FlagStatus lowerLEDMaster, FlagStatus mosfetOutMaster, FlagStatus beepsBackwards) 274 | { 275 | uint8_t index = 0; 276 | uint16_t crc = 0; 277 | uint8_t buffer[USART_MASTERSLAVE_TX_BYTES]; 278 | 279 | uint8_t sendByte = 0; 280 | sendByte |= (0 << 7); 281 | sendByte |= (0 << 6); 282 | sendByte |= (0 << 5); 283 | sendByte |= (0 << 4); 284 | sendByte |= (beepsBackwards << 3); 285 | sendByte |= (mosfetOutMaster << 2); 286 | sendByte |= (lowerLEDMaster << 1); 287 | sendByte |= (upperLEDMaster << 0); 288 | 289 | // Send answer 290 | buffer[index++] = '/'; 291 | buffer[index++] = sendByte; 292 | 293 | // Calculate CRC 294 | crc = CalcCRC(buffer, index); 295 | buffer[index++] = (crc >> 8) & 0xFF; 296 | buffer[index++] = crc & 0xFF; 297 | 298 | // Stop byte 299 | buffer[index++] = '\n'; 300 | 301 | SendBuffer(USART_MASTERSLAVE, buffer, index); 302 | } 303 | 304 | //---------------------------------------------------------------------------- 305 | // Checks input value from master to set value depending on identifier 306 | //---------------------------------------------------------------------------- 307 | void CheckGeneralValue(uint8_t identifier, int16_t value) 308 | { 309 | switch(identifier) 310 | { 311 | case 0: 312 | currentDCMaster = value; 313 | break; 314 | case 1: 315 | batteryMaster = value; 316 | break; 317 | case 2: 318 | realSpeedMaster = value; 319 | break; 320 | case 3: 321 | break; 322 | default: 323 | break; 324 | } 325 | } 326 | 327 | //---------------------------------------------------------------------------- 328 | // Returns current value sent by master 329 | //---------------------------------------------------------------------------- 330 | int16_t GetCurrentDCMaster(void) 331 | { 332 | return currentDCMaster; 333 | } 334 | 335 | //---------------------------------------------------------------------------- 336 | // Returns battery value sent by master 337 | //---------------------------------------------------------------------------- 338 | int16_t GetBatteryMaster(void) 339 | { 340 | return batteryMaster; 341 | } 342 | 343 | //---------------------------------------------------------------------------- 344 | // Returns realspeed value sent by master 345 | //---------------------------------------------------------------------------- 346 | int16_t GetRealSpeedMaster(void) 347 | { 348 | return realSpeedMaster; 349 | } 350 | 351 | //---------------------------------------------------------------------------- 352 | // Sets upper LED value which will be send to master 353 | //---------------------------------------------------------------------------- 354 | void SetUpperLEDMaster(FlagStatus value) 355 | { 356 | upperLEDMaster = value; 357 | } 358 | 359 | //---------------------------------------------------------------------------- 360 | // Returns upper LED value sent by master 361 | //---------------------------------------------------------------------------- 362 | FlagStatus GetUpperLEDMaster(void) 363 | { 364 | return upperLEDMaster; 365 | } 366 | 367 | //---------------------------------------------------------------------------- 368 | // Sets lower LED value which will be send to master 369 | //---------------------------------------------------------------------------- 370 | void SetLowerLEDMaster(FlagStatus value) 371 | { 372 | lowerLEDMaster = value; 373 | } 374 | 375 | //---------------------------------------------------------------------------- 376 | // Returns lower LED value sent by master 377 | //---------------------------------------------------------------------------- 378 | FlagStatus GetLowerLEDMaster(void) 379 | { 380 | return lowerLEDMaster; 381 | } 382 | 383 | //---------------------------------------------------------------------------- 384 | // Sets mosfetOut value which will be send to master 385 | //---------------------------------------------------------------------------- 386 | void SetMosfetOutMaster(FlagStatus value) 387 | { 388 | mosfetOutMaster = value; 389 | } 390 | 391 | //---------------------------------------------------------------------------- 392 | // Returns MosfetOut value sent by master 393 | //---------------------------------------------------------------------------- 394 | FlagStatus GetMosfetOutMaster(void) 395 | { 396 | return mosfetOutMaster; 397 | } 398 | 399 | //---------------------------------------------------------------------------- 400 | // Sets beepsBackwards value which will be send to master 401 | //---------------------------------------------------------------------------- 402 | void SetBeepsBackwardsMaster(FlagStatus value) 403 | { 404 | beepsBackwardsMaster = value; 405 | } 406 | 407 | //---------------------------------------------------------------------------- 408 | // Returns beepsBackwardsMaster value sent by master 409 | //---------------------------------------------------------------------------- 410 | FlagStatus GetBeepsBackwardsMaster(void) 411 | { 412 | return beepsBackwardsMaster; 413 | } 414 | #endif 415 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Src/commsSteering.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "gd32f1x0.h" 32 | #include "../Inc/it.h" 33 | #include "../Inc/comms.h" 34 | #include "../Inc/commsSteering.h" 35 | #include "../Inc/setup.h" 36 | #include "../Inc/config.h" 37 | #include "../Inc/defines.h" 38 | #include "../Inc/bldc.h" 39 | #include "stdio.h" 40 | #include "string.h" 41 | 42 | // Only master communicates with steerin device 43 | #ifdef MASTER 44 | #define USART_STEER_TX_BYTES 2 // Transmit byte count including start '/' and stop character '\n' 45 | #define USART_STEER_RX_BYTES 8 // Receive byte count including start '/' and stop character '\n' 46 | 47 | extern uint8_t usartSteer_COM_rx_buf[USART_STEER_COM_RX_BUFFERSIZE]; 48 | static uint8_t sSteerRecord = 0; 49 | static uint8_t sUSARTSteerRecordBuffer[USART_STEER_RX_BYTES]; 50 | static uint8_t sUSARTSteerRecordBufferCounter = 0; 51 | 52 | void CheckUSARTSteerInput(uint8_t u8USARTBuffer[]); 53 | 54 | extern int32_t steer; 55 | extern int32_t speed; 56 | 57 | //---------------------------------------------------------------------------- 58 | // Send frame to steer device 59 | //---------------------------------------------------------------------------- 60 | void SendSteerDevice(void) 61 | { 62 | int index = 0; 63 | uint8_t buffer[USART_STEER_TX_BYTES]; 64 | 65 | // Ask for steer input 66 | buffer[index++] = '/'; 67 | buffer[index++] = '\n'; 68 | 69 | SendBuffer(USART_STEER_COM, buffer, index); 70 | } 71 | 72 | //---------------------------------------------------------------------------- 73 | // Update USART steer input 74 | //---------------------------------------------------------------------------- 75 | void UpdateUSARTSteerInput(void) 76 | { 77 | uint8_t character = usartSteer_COM_rx_buf[0]; 78 | 79 | // Start character is captured, start record 80 | if (character == '/') 81 | { 82 | sUSARTSteerRecordBufferCounter = 0; 83 | sSteerRecord = 1; 84 | } 85 | 86 | if (sSteerRecord) 87 | { 88 | sUSARTSteerRecordBuffer[sUSARTSteerRecordBufferCounter] = character; 89 | sUSARTSteerRecordBufferCounter++; 90 | 91 | if (sUSARTSteerRecordBufferCounter >= USART_STEER_RX_BYTES) 92 | { 93 | sUSARTSteerRecordBufferCounter = 0; 94 | sSteerRecord = 0; 95 | 96 | // Check input 97 | CheckUSARTSteerInput (sUSARTSteerRecordBuffer); 98 | } 99 | } 100 | } 101 | 102 | //---------------------------------------------------------------------------- 103 | // Check USART steer input 104 | //---------------------------------------------------------------------------- 105 | void CheckUSARTSteerInput(uint8_t USARTBuffer[]) 106 | { 107 | // Auxiliary variables 108 | uint16_t crc; 109 | 110 | // Check start and stop character 111 | if ( USARTBuffer[0] != '/' || 112 | USARTBuffer[USART_STEER_RX_BYTES - 1] != '\n') 113 | { 114 | return; 115 | } 116 | 117 | // Calculate CRC (first bytes except crc and stop byte) 118 | crc = CalcCRC(USARTBuffer, USART_STEER_RX_BYTES - 3); 119 | 120 | // Check CRC 121 | if ( USARTBuffer[USART_STEER_RX_BYTES - 3] != ((crc >> 8) & 0xFF) || 122 | USARTBuffer[USART_STEER_RX_BYTES - 2] != (crc & 0xFF)) 123 | { 124 | return; 125 | } 126 | 127 | // Calculate result speed value -1000 to 1000 128 | speed = (int16_t)((USARTBuffer[1] << 8) | USARTBuffer[2]); 129 | 130 | // Calculate result steering value -1000 to 1000 131 | steer = (int16_t)((USARTBuffer[3] << 8) | USARTBuffer[4]); 132 | 133 | // Reset the pwm timout to avoid stopping motors 134 | ResetTimeout(); 135 | } 136 | #endif 137 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Src/it.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "gd32f1x0.h" 32 | #include "../Inc/it.h" 33 | #include "../Inc/defines.h" 34 | #include "../Inc/config.h" 35 | #include "../Inc/bldc.h" 36 | #include "../Inc/led.h" 37 | #include "../Inc/commsMasterSlave.h" 38 | #include "../Inc/commsSteering.h" 39 | #include "../Inc/commsBluetooth.h" 40 | 41 | uint32_t msTicks; 42 | uint32_t timeoutCounter_ms = 0; 43 | FlagStatus timedOut = SET; 44 | 45 | #ifdef SLAVE 46 | uint32_t hornCounter_ms = 0; 47 | #endif 48 | 49 | extern int32_t steer; 50 | extern int32_t speed; 51 | extern FlagStatus activateWeakening; 52 | extern FlagStatus beepsBackwards; 53 | 54 | //---------------------------------------------------------------------------- 55 | // SysTick_Handler 56 | //---------------------------------------------------------------------------- 57 | void SysTick_Handler(void) 58 | { 59 | msTicks++; 60 | } 61 | 62 | //---------------------------------------------------------------------------- 63 | // Resets the timeout to zero 64 | //---------------------------------------------------------------------------- 65 | void ResetTimeout(void) 66 | { 67 | timeoutCounter_ms = 0; 68 | } 69 | 70 | //---------------------------------------------------------------------------- 71 | // Timer13_Update_Handler 72 | // Is called when upcouting of timer13 is finished and the UPDATE-flag is set 73 | // -> period of timer13 running with 1kHz -> interrupt every 1ms 74 | //---------------------------------------------------------------------------- 75 | void TIMER13_IRQHandler(void) 76 | { 77 | if (timeoutCounter_ms > TIMEOUT_MS) 78 | { 79 | // First timeout reset all process values 80 | if (timedOut == RESET) 81 | { 82 | #ifdef MASTER 83 | steer = 0; 84 | speed = 0; 85 | beepsBackwards = RESET; 86 | #endif 87 | #ifdef SLAVE 88 | SetPWM(0); 89 | #endif 90 | } 91 | 92 | timedOut = SET; 93 | } 94 | else 95 | { 96 | timedOut = RESET; 97 | timeoutCounter_ms++; 98 | } 99 | 100 | #ifdef SLAVE 101 | if (hornCounter_ms >= 2000) 102 | { 103 | // Avoid horn to be activated longer than 2 seconds 104 | SetUpperLEDMaster(RESET); 105 | } 106 | else if (hornCounter_ms < 2000) 107 | { 108 | hornCounter_ms++; 109 | } 110 | 111 | // Update LED program 112 | CalculateLEDProgram(); 113 | #endif 114 | 115 | // Clear timer update interrupt flag 116 | timer_interrupt_flag_clear(TIMER13, TIMER_INT_UP); 117 | } 118 | 119 | //---------------------------------------------------------------------------- 120 | // Timer0_Update_Handler 121 | // Is called when upcouting of timer0 is finished and the UPDATE-flag is set 122 | // AND when downcouting of timer0 is finished and the UPDATE-flag is set 123 | // -> pwm of timer0 running with 16kHz -> interrupt every 31,25us 124 | //---------------------------------------------------------------------------- 125 | void TIMER0_BRK_UP_TRG_COM_IRQHandler(void) 126 | { 127 | // Start ADC conversion 128 | adc_software_trigger_enable(ADC_REGULAR_CHANNEL); 129 | 130 | // Clear timer update interrupt flag 131 | timer_interrupt_flag_clear(TIMER_BLDC, TIMER_INT_UP); 132 | } 133 | 134 | //---------------------------------------------------------------------------- 135 | // This function handles DMA_Channel0_IRQHandler interrupt 136 | // Is called, when the ADC scan sequence is finished 137 | // -> ADC is triggered from timer0-update-interrupt -> every 31,25us 138 | //---------------------------------------------------------------------------- 139 | void DMA_Channel0_IRQHandler(void) 140 | { 141 | // Calculate motor PWMs 142 | CalculateBLDC(); 143 | 144 | #ifdef SLAVE 145 | // Calculates RGB LED 146 | CalculateLEDPWM(); 147 | #endif 148 | 149 | if (dma_interrupt_flag_get(DMA_CH0, DMA_INT_FLAG_FTF)) 150 | { 151 | dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FLAG_FTF); 152 | } 153 | } 154 | 155 | 156 | //---------------------------------------------------------------------------- 157 | // This function handles DMA_Channel1_2_IRQHandler interrupt 158 | // Is asynchronously called when USART0 RX finished 159 | //---------------------------------------------------------------------------- 160 | void DMA_Channel1_2_IRQHandler(void) 161 | { 162 | // USART steer/bluetooth RX 163 | if (dma_interrupt_flag_get(DMA_CH2, DMA_INT_FLAG_FTF)) 164 | { 165 | #ifdef MASTER 166 | // Update USART steer input mechanism 167 | UpdateUSARTSteerInput(); 168 | #endif 169 | #ifdef SLAVE 170 | // Update USART bluetooth input mechanism 171 | UpdateUSARTBluetoothInput(); 172 | #endif 173 | dma_interrupt_flag_clear(DMA_CH2, DMA_INT_FLAG_FTF); 174 | } 175 | } 176 | 177 | 178 | //---------------------------------------------------------------------------- 179 | // This function handles DMA_Channel3_4_IRQHandler interrupt 180 | // Is asynchronously called when USART_SLAVE RX finished 181 | //---------------------------------------------------------------------------- 182 | void DMA_Channel3_4_IRQHandler(void) 183 | { 184 | // USART master slave RX 185 | if (dma_interrupt_flag_get(DMA_CH4, DMA_INT_FLAG_FTF)) 186 | { 187 | // Update USART master slave input mechanism 188 | UpdateUSARTMasterSlaveInput(); 189 | 190 | dma_interrupt_flag_clear(DMA_CH4, DMA_INT_FLAG_FTF); 191 | } 192 | } 193 | 194 | //---------------------------------------------------------------------------- 195 | // Returns number of milliseconds since system start 196 | //---------------------------------------------------------------------------- 197 | uint32_t millis() 198 | { 199 | return msTicks; 200 | } 201 | 202 | //---------------------------------------------------------------------------- 203 | // Delays number of tick Systicks (happens every 10 ms) 204 | //---------------------------------------------------------------------------- 205 | void Delay (uint32_t dlyTicks) 206 | { 207 | uint32_t curTicks; 208 | 209 | curTicks = msTicks; 210 | while ((msTicks - curTicks) < dlyTicks) 211 | { 212 | __NOP(); 213 | } 214 | } 215 | 216 | //---------------------------------------------------------------------------- 217 | // This function handles Non maskable interrupt. 218 | //---------------------------------------------------------------------------- 219 | void NMI_Handler(void) 220 | { 221 | } 222 | 223 | //---------------------------------------------------------------------------- 224 | // This function handles Hard fault interrupt. 225 | //---------------------------------------------------------------------------- 226 | void HardFault_Handler(void) 227 | { 228 | while(1) {} 229 | } 230 | 231 | //---------------------------------------------------------------------------- 232 | // This function handles Memory management fault. 233 | //---------------------------------------------------------------------------- 234 | void MemManage_Handler(void) 235 | { 236 | while(1) {} 237 | } 238 | 239 | //---------------------------------------------------------------------------- 240 | // This function handles Prefetch fault, memory access fault. 241 | //---------------------------------------------------------------------------- 242 | void BusFault_Handler(void) 243 | { 244 | while(1) {} 245 | } 246 | 247 | //---------------------------------------------------------------------------- 248 | // This function handles Undefined instruction or illegal state. 249 | //---------------------------------------------------------------------------- 250 | void UsageFault_Handler(void) 251 | { 252 | while(1) {} 253 | } 254 | 255 | //---------------------------------------------------------------------------- 256 | // This function handles System service call via SWI instruction. 257 | //---------------------------------------------------------------------------- 258 | void SVC_Handler(void) 259 | { 260 | } 261 | 262 | //---------------------------------------------------------------------------- 263 | // This function handles Debug monitor. 264 | //---------------------------------------------------------------------------- 265 | void DebugMon_Handler(void) 266 | { 267 | } 268 | 269 | //---------------------------------------------------------------------------- 270 | // This function handles Pendable request for system service. 271 | //---------------------------------------------------------------------------- 272 | void PendSV_Handler(void) 273 | { 274 | } 275 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Src/led.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "gd32f1x0.h" 32 | #include "../Inc/led.h" 33 | #include "../Inc/defines.h" 34 | 35 | // Only slave has LED mechanism 36 | #ifdef SLAVE 37 | 38 | // Lookuptable for brightness 39 | static unsigned char su8BrightnessTable[64] = 40 | {0,0,1,1,1,2,2,2,2,2,2,3,3,3,3,4,4,4,5,5,6, 41 | 6,7,8,8,9,10,11,12,13,14,15,17,18,20,22,24, 42 | 26,28,31,34,37,40,44,48,52,57,62,68,74,81,89, 43 | 97,106,116,126,138,150,164,179,196,214,234,255}; 44 | 45 | // Variables for RGB output 46 | uint8_t counter_Red = 0; 47 | uint8_t counter_Green = 0; 48 | uint8_t counter_Blue = 0; 49 | uint8_t setValue_Red = 0; 50 | uint8_t setValue_Green = 0; 51 | uint8_t setValue_Blue = 0; 52 | 53 | // Variables for HSB calculation 54 | static uint16_t hueValue = 0; 55 | static uint8_t saturationValue = 128; 56 | static uint8_t brightnessValue = 63; 57 | 58 | // Variable for LED-program 59 | static LED_PROGRAM sLEDProgram = LED_OFF; 60 | 61 | // Variables for effects 62 | static uint16_t speedFading = 150; // Fading-Delay 63 | static uint16_t speedBlink = 1274; // Blink-Delay 64 | static uint16_t speedStrobe = 40; // Strobe-Delay 65 | 66 | // Counter for effects 67 | static uint16_t fadingCounter = 0; 68 | static uint16_t blinkCounter = 0; 69 | static uint16_t strobeCounter = 0; 70 | static FlagStatus strobeToggle = RESET; 71 | 72 | // Prototypes 73 | uint8_t HSBtoRed(uint16_t hue, uint8_t sat); 74 | uint8_t HSBtoGreen(uint16_t hue, uint8_t sat); 75 | uint8_t HSBtoBlue(uint16_t hue, uint8_t sat); 76 | 77 | //---------------------------------------------------------------------------- 78 | // Update RGB LED output with 16kHz 79 | //---------------------------------------------------------------------------- 80 | void CalculateLEDPWM(void) 81 | { 82 | // Upcounting with overflow 83 | counter_Red++; 84 | counter_Green++; 85 | counter_Blue++; 86 | 87 | // Set LEDs 88 | gpio_bit_write(UPPER_LED_PORT, UPPER_LED_PIN, counter_Red >= setValue_Red ? RESET : SET); 89 | gpio_bit_write(LOWER_LED_PORT, LOWER_LED_PIN, counter_Green >= setValue_Green ? RESET : SET); 90 | gpio_bit_write(MOSFET_OUT_PORT, MOSFET_OUT_PIN, counter_Blue >= setValue_Blue ? RESET : SET); 91 | } 92 | 93 | //---------------------------------------------------------------------------- 94 | // Update RGB LED program every 1ms 95 | //---------------------------------------------------------------------------- 96 | void CalculateLEDProgram(void) 97 | { 98 | if (GetRGBProgram() == LED_HSB_FADE) 99 | { 100 | fadingCounter++; 101 | if(fadingCounter >= GetSpeedFading()) 102 | { 103 | fadingCounter = 0; 104 | SetHSBHue(GetHSBHue()+1); 105 | } 106 | } 107 | if (GetRGBProgram() == LED_HSB_BLINK) 108 | { 109 | blinkCounter++; 110 | if(blinkCounter >= GetSpeedBlink()) 111 | { 112 | blinkCounter = 0; 113 | SetHSBHue(GetHSBHue()+50); 114 | } 115 | } 116 | if(GetRGBProgram() == LED_HSB_STROBE) 117 | { 118 | strobeCounter++; 119 | if(strobeCounter >= GetSpeedStrobe()) 120 | { 121 | strobeCounter = 0; 122 | if(strobeToggle == RESET) 123 | { 124 | strobeToggle = SET; 125 | SetHSBBrightness(0); 126 | } 127 | else 128 | { 129 | strobeToggle = RESET; 130 | SetHSBBrightness(63); 131 | } 132 | } 133 | } 134 | } 135 | 136 | //---------------------------------------------------------------------------- 137 | // Sets LED program 138 | //---------------------------------------------------------------------------- 139 | void SetRGBProgram(LED_PROGRAM Program) 140 | { 141 | // Check program count 142 | if(!(Program < COUNT_PROGRAMS)) 143 | { 144 | Program = LED_OFF; 145 | } 146 | 147 | // Save program for later 148 | sLEDProgram = Program; 149 | 150 | switch(Program) 151 | { 152 | case LED_HSB: 153 | case LED_HSB_BLINK: 154 | case LED_HSB_FADE: 155 | case LED_HSB_STROBE: 156 | SetHSBHue(hueValue); 157 | SetHSBSaturation(saturationValue); 158 | SetHSBBrightness(brightnessValue); 159 | break; 160 | case LED_OFF: 161 | default: 162 | setValue_Red = 0; 163 | setValue_Green = 0; 164 | setValue_Blue = 0; 165 | break; 166 | } 167 | } 168 | 169 | //---------------------------------------------------------------------------- 170 | // Gets LED program 171 | //---------------------------------------------------------------------------- 172 | LED_PROGRAM GetRGBProgram(void) 173 | { 174 | return sLEDProgram; 175 | } 176 | 177 | //---------------------------------------------------------------------------- 178 | // Sets hue from 0-764 179 | //---------------------------------------------------------------------------- 180 | void SetHSBHue(uint16_t hue) 181 | { 182 | uint8_t brightness = 0; 183 | 184 | // Save hue for later 185 | if (hue > 764) 186 | { 187 | hueValue = 0; 188 | } 189 | else 190 | { 191 | hueValue = hue; 192 | } 193 | 194 | // Calculate brightness with the lookuptable 195 | brightness = su8BrightnessTable[brightnessValue]; //input: 0..63 output: 0..255 196 | 197 | // Calculate RGB values 198 | setValue_Red = ((brightness + 1) * HSBtoRed(hueValue, saturationValue)) >> 8; 199 | setValue_Green = ((brightness + 1) * HSBtoGreen(hueValue, saturationValue)) >> 8; 200 | setValue_Blue = ((brightness + 1) * HSBtoBlue(hueValue, saturationValue)) >> 8; 201 | } 202 | 203 | //---------------------------------------------------------------------------- 204 | // Gets hue from 0-764 205 | //---------------------------------------------------------------------------- 206 | uint16_t GetHSBHue(void) 207 | { 208 | return hueValue; 209 | } 210 | 211 | //---------------------------------------------------------------------------- 212 | // Sets saturation from 0-128 213 | //---------------------------------------------------------------------------- 214 | void SetHSBSaturation(uint8_t saturation) 215 | { 216 | uint8_t brightness = 0; 217 | 218 | // Save Saturation for later 219 | saturationValue = MAX(saturation, 128); 220 | 221 | // Calculate brightness with the lookuptable 222 | brightness = su8BrightnessTable[brightnessValue]; //input: 0..63 output: 0..255 223 | 224 | // Calculate RGB values 225 | setValue_Red = ((brightness + 1) * HSBtoRed(hueValue, saturationValue)) >> 8; 226 | setValue_Green = ((brightness + 1) * HSBtoGreen(hueValue, saturationValue)) >> 8; 227 | setValue_Blue = ((brightness + 1) * HSBtoBlue(hueValue, saturationValue)) >> 8; 228 | } 229 | 230 | //---------------------------------------------------------------------------- 231 | // Gets saturation from 0-128 232 | //---------------------------------------------------------------------------- 233 | uint8_t GetHSBSaturation(void) 234 | { 235 | return saturationValue; 236 | } 237 | 238 | //---------------------------------------------------------------------------- 239 | // Sets brightness from 0-63 240 | //---------------------------------------------------------------------------- 241 | void SetHSBBrightness(uint8_t brightnessVal) 242 | { 243 | uint8_t brightness = 0; 244 | 245 | // Save brightness for later 246 | brightnessValue = MAX(brightnessVal, 63); 247 | 248 | // Calculate brightness with the lookuptable 249 | brightness = su8BrightnessTable[brightnessValue]; //input: 0..63 output: 0..255 250 | 251 | // Calculate RGB values 252 | setValue_Red = ((brightness + 1) * HSBtoRed(hueValue, saturationValue)) >> 8; 253 | setValue_Green = ((brightness + 1) * HSBtoGreen(hueValue, saturationValue)) >> 8; 254 | setValue_Blue = ((brightness + 1) * HSBtoBlue(hueValue, saturationValue)) >> 8; 255 | } 256 | 257 | //---------------------------------------------------------------------------- 258 | // Gets brightness from 0-63 259 | //---------------------------------------------------------------------------- 260 | uint8_t GetHSBBrightness(void) 261 | { 262 | return brightnessValue; 263 | } 264 | 265 | //---------------------------------------------------------------------------- 266 | // Sets fading speed from 200-1000 267 | //---------------------------------------------------------------------------- 268 | void SetSpeedFading(uint16_t speed) 269 | { 270 | speedFading = CLAMP(speed, 200, 1000); 271 | } 272 | 273 | //---------------------------------------------------------------------------- 274 | // Gets fading speed from 200-1000 275 | //---------------------------------------------------------------------------- 276 | uint16_t GetSpeedFading(void) 277 | { 278 | return speedFading; 279 | } 280 | 281 | //---------------------------------------------------------------------------- 282 | // Sets blink speed from 700-2400 283 | //---------------------------------------------------------------------------- 284 | void SetSpeedBlink(uint16_t speed) 285 | { 286 | speedBlink = CLAMP(speed, 700, 2400); 287 | } 288 | 289 | //---------------------------------------------------------------------------- 290 | // Gets blink speed from 700-2400 291 | //---------------------------------------------------------------------------- 292 | uint16_t GetSpeedBlink(void) 293 | { 294 | return speedBlink; 295 | } 296 | 297 | //---------------------------------------------------------------------------- 298 | // Sets strobe speed from 0-1000 299 | //---------------------------------------------------------------------------- 300 | void SetSpeedStrobe(uint16_t speed) 301 | { 302 | speedStrobe = CLAMP(speed, 40, 400); 303 | } 304 | 305 | //---------------------------------------------------------------------------- 306 | // Gets strobe speed from 0-1000 307 | //---------------------------------------------------------------------------- 308 | uint16_t GetSpeedStrobe(void) 309 | { 310 | return speedStrobe; 311 | } 312 | 313 | //---------------------------------------------------------------------------- 314 | // Hue to red 315 | //---------------------------------------------------------------------------- 316 | uint8_t HSBtoRed(uint16_t hue, uint8_t sat) 317 | { 318 | unsigned char red_val = 0; 319 | 320 | if (hue > 764) 321 | { 322 | hue = 0; 323 | } 324 | if (hue < 255) 325 | { 326 | red_val = (10880 - sat * (hue - 170)) >> 7; 327 | } 328 | else if (hue < 510) 329 | { 330 | red_val = (10880 - sat * 85) >> 7; 331 | } 332 | else 333 | { 334 | red_val = (10880 - sat * (595 - hue)) >> 7; 335 | } 336 | 337 | return red_val; 338 | } 339 | 340 | //---------------------------------------------------------------------------- 341 | // Hue to green 342 | //---------------------------------------------------------------------------- 343 | uint8_t HSBtoGreen(uint16_t hue, uint8_t sat) 344 | { 345 | uint8_t green_val = 0; 346 | 347 | if (hue > 764) 348 | { 349 | hue = 0; 350 | } 351 | if (hue < 255) 352 | { 353 | green_val = (10880 - sat * (85 - hue)) >> 7; 354 | } 355 | else if (hue < 510) 356 | { 357 | green_val = (10880 - sat * (hue - 425)) >> 7; 358 | } 359 | else 360 | { 361 | green_val = (10880 - sat * 85) >> 7; 362 | } 363 | 364 | return green_val; 365 | } 366 | 367 | //---------------------------------------------------------------------------- 368 | // Hue to blue 369 | //---------------------------------------------------------------------------- 370 | uint8_t HSBtoBlue(uint16_t hue, uint8_t sat) 371 | { 372 | uint8_t blue_val = 0; 373 | 374 | if (hue > 764) 375 | { 376 | hue = 0; 377 | } 378 | if (hue < 255) 379 | { 380 | blue_val = (10880 - sat * 85) >> 7; 381 | } 382 | else if (hue < 510) 383 | { 384 | blue_val = (10880 - sat * (340 - hue)) >> 7; 385 | } 386 | else 387 | { 388 | blue_val = (10880 - sat * (hue - 680)) >> 7; 389 | } 390 | 391 | return blue_val; 392 | } 393 | #endif 394 | -------------------------------------------------------------------------------- /HoverBoardGigaDevice/Src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #define ARM_MATH_CM3 32 | 33 | #include "gd32f1x0.h" 34 | 35 | #include "../Inc/setup.h" 36 | #include "../Inc/defines.h" 37 | #include "../Inc/config.h" 38 | #include "../Inc/it.h" 39 | #include "../Inc/bldc.h" 40 | #include "../Inc/commsMasterSlave.h" 41 | #include "../Inc/commsSteering.h" 42 | #include "../Inc/commsBluetooth.h" 43 | #include "stdio.h" 44 | #include "stdlib.h" 45 | #include "string.h" 46 | #include 47 | #include "arm_math.h" 48 | 49 | #ifdef MASTER 50 | int32_t steer = 0; // global variable for steering. -1000 to 1000 51 | int32_t speed = 0; // global variable for speed. -1000 to 1000 52 | FlagStatus activateWeakening = RESET; // global variable for weakening 53 | FlagStatus beepsBackwards = RESET; // global variable for beeps backwards 54 | 55 | extern uint8_t buzzerFreq; // global variable for the buzzer pitch. can be 1, 2, 3, 4, 5, 6, 7... 56 | extern uint8_t buzzerPattern; // global variable for the buzzer pattern. can be 1, 2, 3, 4, 5, 6, 7... 57 | 58 | extern float batteryVoltage; // global variable for battery voltage 59 | extern float currentDC; // global variable for current dc 60 | extern float realSpeed; // global variable for real Speed 61 | uint8_t slaveError = 0; // global variable for slave error 62 | 63 | extern FlagStatus timedOut; // Timeoutvariable set by timeout timer 64 | 65 | uint32_t inactivity_timeout_counter = 0; // Inactivity counter 66 | uint32_t steerCounter = 0; // Steer counter for setting update rate 67 | 68 | void ShowBatteryState(uint32_t pin); 69 | void BeepsBackwards(FlagStatus beepsBackwards); 70 | void ShutOff(void); 71 | #endif 72 | 73 | const float lookUpTableAngle[181] = 74 | { 75 | -1, 76 | -0.937202577, 77 | -0.878193767, 78 | -0.822607884, 79 | -0.770124422, 80 | -0.720461266, 81 | -0.673369096, 82 | -0.628626737, 83 | -0.58603728, 84 | -0.545424828, 85 | -0.506631749, 86 | -0.46951635, 87 | -0.433950895, 88 | -0.399819915, 89 | -0.367018754, 90 | -0.335452314, 91 | -0.30503398, 92 | -0.275684674, 93 | -0.24733204, 94 | -0.219909731, 95 | -0.193356783, 96 | -0.167617063, 97 | -0.142638788, 98 | -0.118374098, 99 | -0.094778672, 100 | -0.071811398, 101 | -0.049434068, 102 | -0.027611115, 103 | -0.006309372, 104 | 0.014502141, 105 | 0.03485241, 106 | 0.054768601, 107 | 0.074276213, 108 | 0.093399224, 109 | 0.112160212, 110 | 0.130580478, 111 | 0.148680146, 112 | 0.166478264, 113 | 0.183992885, 114 | 0.201241154, 115 | 0.218239378, 116 | 0.235003093, 117 | 0.251547129, 118 | 0.267885663, 119 | 0.284032276, 120 | 0.3, 121 | 0.315801365, 122 | 0.331448439, 123 | 0.34695287, 124 | 0.362325923, 125 | 0.377578512, 126 | 0.392721236, 127 | 0.407764409, 128 | 0.422718089, 129 | 0.437592106, 130 | 0.45239609, 131 | 0.467139493, 132 | 0.48183162, 133 | 0.496481645, 134 | 0.511098642, 135 | 0.5256916, 136 | 0.540269454, 137 | 0.554841097, 138 | 0.569415411, 139 | 0.584001283, 140 | 0.598607627, 141 | 0.613243408, 142 | 0.627917665, 143 | 0.642639528, 144 | 0.657418247, 145 | 0.672263213, 146 | 0.687183982, 147 | 0.702190301, 148 | 0.717292134, 149 | 0.732499689, 150 | 0.747823448, 151 | 0.763274197, 152 | 0.778863056, 153 | 0.794601516, 154 | 0.810501473, 155 | 0.826575268, 156 | 0.842835728, 157 | 0.859296209, 158 | 0.875970644, 159 | 0.892873598, 160 | 0.910020317, 161 | 0.927426794, 162 | 0.94510983, 163 | 0.963087109, 164 | 0.981377271, 165 | 1, 166 | 1.018976116, 167 | 1.038327677, 168 | 1.058078086, 169 | 1.07825222, 170 | 1.098876565, 171 | 1.119979359, 172 | 1.141590767, 173 | 1.163743061, 174 | 1.186470823, 175 | 1.209811179, 176 | 1.23380405, 177 | 1.258492439, 178 | 1.283922754, 179 | 1.310145166, 180 | 1.33721402, 181 | 1.365188293, 182 | 1.394132116, 183 | 1.42411537, 184 | 1.455214362, 185 | 1.487512601, 186 | 1.521101681, 187 | 1.556082309, 188 | 1.592565485, 189 | 1.630673867, 190 | 1.670543366, 191 | 1.712325006, 192 | 1.7561871, 193 | 1.802317825, 194 | 1.85092826, 195 | 1.902255998, 196 | 1.956569473, 197 | 2.014173151, 198 | 2.075413814, 199 | 2.140688197, 200 | 2.210452351, 201 | 2.28523318, 202 | 2.365642792, 203 | 2.452396478, 204 | 2.546335439, 205 | 2.648455802, 206 | 2.75994605, 207 | 2.882235846, 208 | 3.01706052, 209 | 3.166547428, 210 | 3.333333333, 211 | 3.520726642, 212 | 3.732935875, 213 | 3.97539819, 214 | 4.255263139, 215 | 4.582124498, 216 | 4.96916252, 217 | 5.434992778, 218 | 6.006790189, 219 | 6.72584757, 220 | 7.658112588, 221 | 8.915817681, 222 | 10.70672711, 223 | 13.46326037, 224 | 18.25863694, 225 | 28.69242032, 226 | 68.95533643, 227 | -158.4943784, 228 | -36.21729907, 229 | -20.22896451, 230 | -13.92536607, 231 | -10.55089693, 232 | -8.447794056, 233 | -7.010715755, 234 | -5.965979741, 235 | -5.171786508, 236 | -4.547320366, 237 | -4.043147824, 238 | -3.62733258, 239 | -3.278323283, 240 | -2.981049637, 241 | -2.72465641, 242 | -2.501126036, 243 | -2.304408198, 244 | -2.129851283, 245 | -1.973820239, 246 | -1.833433222, 247 | -1.706376086, 248 | -1.590769119, 249 | -1.485069639, 250 | -1.387999671, 251 | -1.29849148, 252 | -1.21564602, 253 | -1.138700863, 254 | -1.067005175, 255 | -1 256 | }; 257 | 258 | 259 | //---------------------------------------------------------------------------- 260 | // MAIN function 261 | //---------------------------------------------------------------------------- 262 | int main (void) 263 | { 264 | #ifdef MASTER 265 | FlagStatus enable = RESET; 266 | FlagStatus enableSlave = RESET; 267 | FlagStatus chargeStateLowActive = SET; 268 | int16_t sendSlaveValue = 0; 269 | uint8_t sendSlaveIdentifier = 0; 270 | int8_t index = 8; 271 | int16_t pwmSlave = 0; 272 | int16_t pwmMaster = 0; 273 | int16_t scaledSpeed = 0; 274 | int16_t scaledSteer = 0; 275 | float expo = 0; 276 | float steerAngle = 0; 277 | float xScale = 0; 278 | #endif 279 | 280 | //SystemClock_Config(); 281 | SystemCoreClockUpdate(); 282 | SysTick_Config(SystemCoreClock / 100); 283 | 284 | // Init watchdog 285 | if (Watchdog_init() == ERROR) 286 | { 287 | // If an error accours with watchdog initialization do not start device 288 | while(1); 289 | } 290 | 291 | // Init Interrupts 292 | Interrupt_init(); 293 | 294 | // Init timeout timer 295 | TimeoutTimer_init(); 296 | 297 | // Init GPIOs 298 | GPIO_init(); 299 | 300 | // Activate self hold direct after GPIO-init 301 | gpio_bit_write(SELF_HOLD_PORT, SELF_HOLD_PIN, SET); 302 | 303 | // Init usart master slave 304 | USART_MasterSlave_init(); 305 | 306 | // Init ADC 307 | ADC_init(); 308 | 309 | // Init PWM 310 | PWM_init(); 311 | 312 | // Device has 1,6 seconds to do all the initialization 313 | // afterwards watchdog will be fired 314 | fwdgt_counter_reload(); 315 | 316 | // Init usart steer/bluetooth 317 | USART_Steer_COM_init(); 318 | 319 | #ifdef MASTER 320 | // Startup-Sound 321 | for (; index >= 0; index--) 322 | { 323 | buzzerFreq = index; 324 | Delay(10); 325 | } 326 | buzzerFreq = 0; 327 | 328 | // Wait until button is pressed 329 | while (gpio_input_bit_get(BUTTON_PORT, BUTTON_PIN)) 330 | { 331 | // Reload watchdog while button is pressed 332 | fwdgt_counter_reload(); 333 | } 334 | #endif 335 | 336 | while(1) 337 | { 338 | #ifdef MASTER 339 | steerCounter++; 340 | if ((steerCounter % 2) == 0) 341 | { 342 | // Request steering data 343 | SendSteerDevice(); 344 | } 345 | 346 | // Calculate expo rate for less steering with higher speeds 347 | expo = MAP((float)ABS(speed), 0, 1000, 1, 0.5); 348 | 349 | // Each speedvalue or steervalue between 50 and -50 means absolutely no pwm 350 | // -> to get the device calm 'around zero speed' 351 | scaledSpeed = speed < 50 && speed > -50 ? 0 : CLAMP(speed, -1000, 1000) * SPEED_COEFFICIENT; 352 | scaledSteer = steer < 50 && steer > -50 ? 0 : CLAMP(steer, -1000, 1000) * STEER_COEFFICIENT * expo; 353 | 354 | // Map to an angle of 180 degress to 0 degrees for array access (means angle -90 to 90 degrees) 355 | steerAngle = MAP((float)scaledSteer, -1000, 1000, 180, 0); 356 | xScale = lookUpTableAngle[(uint16_t)steerAngle]; 357 | 358 | // Mix steering and speed value for right and left speed 359 | if(steerAngle >= 90) 360 | { 361 | pwmSlave = CLAMP(scaledSpeed, -1000, 1000); 362 | pwmMaster = CLAMP(pwmSlave / xScale, -1000, 1000); 363 | } 364 | else 365 | { 366 | pwmMaster = CLAMP(scaledSpeed, -1000, 1000); 367 | pwmSlave = CLAMP(xScale * pwmMaster, -1000, 1000); 368 | } 369 | 370 | // Read charge state 371 | chargeStateLowActive = gpio_input_bit_get(CHARGE_STATE_PORT, CHARGE_STATE_PIN); 372 | 373 | // Enable is depending on charger is connected or not 374 | enable = chargeStateLowActive; 375 | 376 | // Enable channel output 377 | SetEnable(enable); 378 | 379 | // Decide if slave will be enabled 380 | enableSlave = (enable == SET && timedOut == RESET) ? SET : RESET; 381 | 382 | // Decide which process value has to be sent 383 | switch(sendSlaveIdentifier) 384 | { 385 | case 0: 386 | sendSlaveValue = currentDC * 100; 387 | break; 388 | case 1: 389 | sendSlaveValue = batteryVoltage * 100; 390 | break; 391 | case 2: 392 | sendSlaveValue = realSpeed * 100; 393 | break; 394 | default: 395 | break; 396 | } 397 | 398 | // Set output 399 | SetPWM(pwmMaster); 400 | SendSlave(-pwmSlave, enableSlave, RESET, chargeStateLowActive, sendSlaveIdentifier, sendSlaveValue); 401 | 402 | // Increment identifier 403 | sendSlaveIdentifier++; 404 | if (sendSlaveIdentifier > 2) 405 | { 406 | sendSlaveIdentifier = 0; 407 | } 408 | 409 | // Show green battery symbol when battery level BAT_LOW_LVL1 is reached 410 | if (batteryVoltage > BAT_LOW_LVL1) 411 | { 412 | // Show green battery light 413 | ShowBatteryState(LED_GREEN); 414 | 415 | // Beeps backwards 416 | BeepsBackwards(beepsBackwards); 417 | } 418 | // Make silent sound and show orange battery symbol when battery level BAT_LOW_LVL2 is reached 419 | else if (batteryVoltage > BAT_LOW_LVL2 && batteryVoltage < BAT_LOW_LVL1) 420 | { 421 | // Show orange battery light 422 | ShowBatteryState(LED_ORANGE); 423 | 424 | buzzerFreq = 5; 425 | buzzerPattern = 8; 426 | } 427 | // Make even more sound and show red battery symbol when battery level BAT_LOW_DEAD is reached 428 | else if (batteryVoltage > BAT_LOW_DEAD && batteryVoltage < BAT_LOW_LVL2) 429 | { 430 | // Show red battery light 431 | ShowBatteryState(LED_RED); 432 | 433 | buzzerFreq = 5; 434 | buzzerPattern = 1; 435 | } 436 | // Shut device off, when battery is dead 437 | else if (batteryVoltage < BAT_LOW_DEAD) 438 | { 439 | ShutOff(); 440 | } 441 | else 442 | { 443 | ShutOff(); 444 | } 445 | 446 | // Shut device off when button is pressed 447 | if (gpio_input_bit_get(BUTTON_PORT, BUTTON_PIN)) 448 | { 449 | while (gpio_input_bit_get(BUTTON_PORT, BUTTON_PIN)) {} 450 | ShutOff(); 451 | } 452 | 453 | // Calculate inactivity timeout (Except, when charger is active -> keep device running) 454 | if (ABS(pwmMaster) > 50 || ABS(pwmSlave) > 50 || !chargeStateLowActive) 455 | { 456 | inactivity_timeout_counter = 0; 457 | } 458 | else 459 | { 460 | inactivity_timeout_counter++; 461 | } 462 | 463 | // Shut off device after INACTIVITY_TIMEOUT in minutes 464 | if (inactivity_timeout_counter > (INACTIVITY_TIMEOUT * 60 * 1000) / (DELAY_IN_MAIN_LOOP + 1)) 465 | { 466 | ShutOff(); 467 | } 468 | #endif 469 | 470 | Delay(DELAY_IN_MAIN_LOOP); 471 | 472 | // Reload watchdog (watchdog fires after 1,6 seconds) 473 | fwdgt_counter_reload(); 474 | } 475 | } 476 | 477 | #ifdef MASTER 478 | //---------------------------------------------------------------------------- 479 | // Turns the device off 480 | //---------------------------------------------------------------------------- 481 | void ShutOff(void) 482 | { 483 | int index = 0; 484 | 485 | buzzerPattern = 0; 486 | for (; index < 8; index++) 487 | { 488 | buzzerFreq = index; 489 | Delay(10); 490 | } 491 | buzzerFreq = 0; 492 | 493 | // Send shut off command to slave 494 | SendSlave(0, RESET, SET, RESET, RESET, RESET); 495 | 496 | // Disable usart 497 | usart_deinit(USART_MASTERSLAVE); 498 | 499 | // Set pwm and enable to off 500 | SetEnable(RESET); 501 | SetPWM(0); 502 | 503 | gpio_bit_write(SELF_HOLD_PORT, SELF_HOLD_PIN, RESET); 504 | while(1) 505 | { 506 | // Reload watchdog until device is off 507 | fwdgt_counter_reload(); 508 | } 509 | } 510 | 511 | //---------------------------------------------------------------------------- 512 | // Shows the battery state on the LEDs 513 | //---------------------------------------------------------------------------- 514 | void ShowBatteryState(uint32_t pin) 515 | { 516 | gpio_bit_write(LED_GREEN_PORT, LED_GREEN, pin == LED_GREEN ? SET : RESET); 517 | gpio_bit_write(LED_ORANGE_PORT, LED_ORANGE, pin == LED_ORANGE ? SET : RESET); 518 | gpio_bit_write(LED_RED_PORT, LED_RED, pin == LED_RED ? SET : RESET); 519 | } 520 | 521 | //---------------------------------------------------------------------------- 522 | // Beeps while driving backwards 523 | //---------------------------------------------------------------------------- 524 | void BeepsBackwards(FlagStatus beepsBackwards) 525 | { 526 | // If the speed is less than -50, beep while driving backwards 527 | if (beepsBackwards == SET && speed < -50) 528 | { 529 | buzzerFreq = 5; 530 | buzzerPattern = 4; 531 | } 532 | else 533 | { 534 | buzzerFreq = 0; 535 | buzzerPattern = 0; 536 | } 537 | } 538 | #endif 539 | -------------------------------------------------------------------------------- /PPMDeviceArduino_V1.0/PPMDevice/PPMDevice.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "RCReceiver.h" 32 | #include "SteeringSerial.h" 33 | #include "utils.h" 34 | 35 | void setup() 36 | { 37 | // Initialize steering serial 38 | InitSteeringSerial(); 39 | 40 | // Enable Debug LED 41 | pinMode(LED_BUILTIN, OUTPUT); 42 | digitalWrite(LED_BUILTIN, 1); 43 | 44 | // Initialize RC receiver 45 | InitRCReceiver(); 46 | 47 | // Start RC receiver 48 | RCReceiverStart(); 49 | } 50 | 51 | void loop() 52 | { 53 | uint16_t channel1 = GetRCValue(0); 54 | uint16_t channel2 = GetRCValue(1); 55 | uint16_t channel3 = GetRCValue(2); 56 | 57 | // Activate/deactivate speed mode 58 | float factor = channel3 < 1500 ? 0.5 : 1; 59 | 60 | // Handle receiver values 61 | SetSpeed(channel1, factor); 62 | SetSteer(channel2); 63 | 64 | /* SendDebug(); */ 65 | 66 | // Reply only when you receive data 67 | if (Serial.available() > 0) 68 | { 69 | char character = Serial.read(); 70 | if (character == '\n') 71 | { 72 | SendAnswer(); 73 | } 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /PPMDeviceArduino_V1.0/PPMDevice/RCReceiver.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "RCReceiver.h" 32 | 33 | uint16_t m_pulseStart[SERVOS]; // Last measured pulse start for each input. 34 | uint16_t m_pulseLength_us[SERVOS]; // Last measured pulse length for each input. 35 | static uint8_t lastB = 0; 36 | volatile static bool enable = false; 37 | volatile static bool pinChangeActive = false; 38 | 39 | uint16_t RCReceiverGetStartCount(); 40 | uint16_t RCReceiverGetStopCount(uint8_t p_servo); 41 | uint16_t RCReceiverGetCnt(); 42 | 43 | //---------------------------------------------------------------------------- 44 | // Initializes the steering serial 45 | //---------------------------------------------------------------------------- 46 | void InitRCReceiver(void) 47 | { 48 | // Deinitialize timer1 49 | TCCR1A = 0; 50 | TCCR1B = 0; 51 | TCCR1C = 0; 52 | TIMSK1 = 0; 53 | OCR1A = 0; 54 | OCR1B = 0; 55 | TCNT1 = 0; 56 | 57 | // We use pin 8-10 PB0, PB1, PB2 as Servo input pins 58 | pinMode(8, INPUT); 59 | pinMode(9, INPUT); 60 | pinMode(10, INPUT); 61 | 62 | // We use pin change interrupts to detect changes in the signal 63 | // Only allow pin change interrupts for PB0-3 (digital pins 8-10) 64 | PCMSK0 |= (1 << PCINT0) | (1 << PCINT1) | (1 << PCINT2); 65 | 66 | // Enable pin change interrupt 0 67 | PCICR |= (1 << PCIE0); 68 | } 69 | 70 | //---------------------------------------------------------------------------- 71 | // Starts the receiver 72 | //---------------------------------------------------------------------------- 73 | void RCReceiverStart() 74 | { 75 | // Clean buffers 76 | for (uint8_t i = 0; i < SERVOS; ++i) 77 | { 78 | m_pulseStart[i] = 0; 79 | m_pulseLength_us[i] = ZERO_US; 80 | } 81 | 82 | // Start Timer 1 83 | // Timer 1 counts up with 1MHz, so that 1 count = 1us 84 | // Overflow interrupt after 1000000MHz / 65536 = 0,065536s -> every 65,5ms 85 | TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11) | _BV(CS10))) | _BV(CS11); 86 | TIMSK1 |= _BV(TOIE1); 87 | } 88 | 89 | //---------------------------------------------------------------------------- 90 | // Returns the current result value of specified pin 91 | //---------------------------------------------------------------------------- 92 | uint16_t GetRCValue(uint8_t pin) 93 | { 94 | if (pin < 0 || pin > SERVOS) 95 | { 96 | return ZERO_US; 97 | } 98 | return m_pulseLength_us[pin]; 99 | } 100 | 101 | //---------------------------------------------------------------------------- 102 | // Will be called when a reciever pin changes 103 | //---------------------------------------------------------------------------- 104 | void RCReceiverPinChanged(uint8_t p_servo, bool p_high) 105 | { 106 | if (p_high) 107 | { 108 | // Start of pulse 109 | m_pulseStart[p_servo] = RCReceiverGetStartCount(); 110 | } 111 | else 112 | { 113 | // End of pulse 114 | m_pulseLength_us[p_servo] = CLAMP(RCReceiverGetStopCount(p_servo), 1000, 2000); 115 | } 116 | } 117 | 118 | //---------------------------------------------------------------------------- 119 | // Returns the start count of the timer 120 | //---------------------------------------------------------------------------- 121 | uint16_t RCReceiverGetStartCount() 122 | { 123 | uint16_t cnt = RCReceiverGetCnt(); 124 | 125 | // Start of pulse 126 | return cnt; 127 | } 128 | 129 | //---------------------------------------------------------------------------- 130 | // Returns the stop count of the specified input pin 131 | //---------------------------------------------------------------------------- 132 | uint16_t RCReceiverGetStopCount(uint8_t p_servo) 133 | { 134 | uint16_t cnt = RCReceiverGetCnt(); 135 | 136 | // End of pulse 137 | return (cnt - m_pulseStart[p_servo]) >> 1; 138 | } 139 | 140 | //---------------------------------------------------------------------------- 141 | // Returns the count value of the timer 142 | //---------------------------------------------------------------------------- 143 | uint16_t RCReceiverGetCnt() 144 | { 145 | uint8_t oldSREG = SREG; 146 | cli(); 147 | uint16_t cnt = TCNT1; 148 | SREG = oldSREG; 149 | 150 | return cnt; 151 | } 152 | 153 | //---------------------------------------------------------------------------- 154 | // Interrupt service routine for timer1 overflow 155 | //---------------------------------------------------------------------------- 156 | ISR(TIMER1_OVF_vect) 157 | { 158 | sei(); 159 | 160 | // Between two overflow interrupts (every 65,5ms) should be 161 | // at least one pin change interrupt (receiver pwm period is 6ms) 162 | if (pinChangeActive) 163 | { 164 | enable = true; 165 | } 166 | else 167 | { 168 | m_pulseLength_us[0] = ZERO_US; 169 | m_pulseLength_us[1] = ZERO_US; 170 | m_pulseLength_us[2] = ZERO_US; 171 | enable = false; 172 | } 173 | pinChangeActive = false; 174 | } 175 | 176 | // 177 | //---------------------------------------------------------------------------- 178 | // Interrupt service routine for pin change port 0 interrupt 179 | //---------------------------------------------------------------------------- 180 | ISR(PCINT0_vect) 181 | { 182 | if (enable == false) 183 | { 184 | pinChangeActive = true; 185 | return; 186 | } 187 | pinChangeActive = true; 188 | uint8_t newB = PINB; 189 | 190 | // Bitwise XOR will set all bits that have changed 191 | uint8_t chgB = newB ^ lastB; 192 | lastB = newB; 193 | 194 | // Has any of the pins changed? 195 | if (chgB) 196 | { 197 | // Find out which pin has changed 198 | if (chgB & _BV(0)) 199 | { 200 | RCReceiverPinChanged(0, newB & _BV(0)); 201 | } 202 | if (chgB & _BV(1)) 203 | { 204 | RCReceiverPinChanged(1, newB & _BV(1)); 205 | } 206 | if (chgB & _BV(2)) 207 | { 208 | RCReceiverPinChanged(2, newB & _BV(2)); 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /PPMDeviceArduino_V1.0/PPMDevice/RCReceiver.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef RCRECEIVER_H 32 | #define RCRECEIVER_H 33 | 34 | #include 35 | #include 36 | #include "utils.h" 37 | //---------------------------------------------------------------------------- 38 | // Defines 39 | //---------------------------------------------------------------------------- 40 | #define SERVOS 3 41 | #define ZERO_US 1500 42 | 43 | //---------------------------------------------------------------------------- 44 | // Initializes the RC receiver 45 | //---------------------------------------------------------------------------- 46 | void InitRCReceiver(void); 47 | 48 | //---------------------------------------------------------------------------- 49 | // Starts the receiver 50 | //---------------------------------------------------------------------------- 51 | void RCReceiverStart(); 52 | 53 | //---------------------------------------------------------------------------- 54 | // Returns the current result value of specified pin 55 | //---------------------------------------------------------------------------- 56 | uint16_t GetRCValue(uint8_t pin); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /PPMDeviceArduino_V1.0/PPMDevice/SteeringSerial.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #include "SteeringSerial.h" 32 | 33 | //---------------------------------------------------------------------------- 34 | // Variables 35 | //---------------------------------------------------------------------------- 36 | int32_t speedValue = 0; 37 | int32_t steerValue = 0; 38 | uint8_t upperLEDMaster = 0; 39 | uint8_t lowerLEDMaster = 0; 40 | uint8_t mosfetOutMaster = 0; 41 | uint8_t upperLEDSlave = 0; 42 | uint8_t lowerLEDSlave = 0; 43 | uint8_t mosfetOutSlave = 0; 44 | uint8_t beepsBackwards = 0; 45 | uint8_t activateWeakening = 0; 46 | 47 | void SendBuffer(uint8_t buffer[], uint8_t length); 48 | uint16_t CalcCRC(uint8_t *ptr, int count); 49 | 50 | //---------------------------------------------------------------------------- 51 | // Initializes the steering serial 52 | //---------------------------------------------------------------------------- 53 | void InitSteeringSerial(void) 54 | { 55 | // Set up serial communication 56 | Serial.begin(19200, SERIAL_8N1); 57 | } 58 | 59 | //---------------------------------------------------------------------------- 60 | // Sets the speed value 61 | //---------------------------------------------------------------------------- 62 | void SetSpeed(uint16_t data, float factor) 63 | { 64 | int16_t tempValue = ((float)data * 2 ) - 3000.0; // Value -1000 to 1000 65 | tempValue *= factor; 66 | tempValue = CLAMP(tempValue, -1000, 1000); // Avoid calculation failure 67 | speedValue = tempValue; 68 | } 69 | 70 | //---------------------------------------------------------------------------- 71 | // Sets the steering value 72 | //---------------------------------------------------------------------------- 73 | void SetSteer(uint16_t data) 74 | { 75 | int16_t tempValue = ((float)data * 2 ) - 3000.0; // Value -1000 to 1000 76 | tempValue = CLAMP(tempValue, -1000, 1000); // Avoid calculation failure 77 | if (speedValue < 0) 78 | { 79 | steerValue *= -1; 80 | } 81 | steerValue = tempValue; 82 | } 83 | 84 | //---------------------------------------------------------------------------- 85 | // Sends answer to master device 86 | //---------------------------------------------------------------------------- 87 | void SendAnswer(void) 88 | { 89 | int index = 0; 90 | uint8_t buffer[9]; 91 | uint8_t byte1 = 0; 92 | uint8_t byte2 = 0; 93 | uint8_t byte3 = 0; 94 | uint8_t byte4 = 0; 95 | 96 | uint8_t sendByte = 0; 97 | sendByte |= (activateWeakening << 7); 98 | sendByte |= (beepsBackwards << 6); 99 | sendByte |= (mosfetOutSlave << 5); 100 | sendByte |= (lowerLEDSlave << 4); 101 | sendByte |= (upperLEDSlave << 3); 102 | sendByte |= (mosfetOutMaster << 2); 103 | sendByte |= (lowerLEDMaster << 1); 104 | sendByte |= (upperLEDMaster << 0); 105 | 106 | uint16_t speedValue_Format = (uint16_t)(speedValue); 107 | byte1 |= (speedValue_Format >> 8) & 0xFF; 108 | byte2 |= speedValue_Format & 0xFF; 109 | 110 | uint16_t steerValue_Format = (uint16_t)(steerValue); 111 | byte3 |= (steerValue_Format >> 8) & 0xFF; 112 | byte4 |= steerValue_Format & 0xFF; 113 | 114 | // Send answer 115 | buffer[index++] = '/'; 116 | buffer[index++] = byte1; 117 | buffer[index++] = byte2; 118 | buffer[index++] = byte3; 119 | buffer[index++] = byte4; 120 | buffer[index++] = sendByte; 121 | 122 | // Calculate CRC 123 | uint16_t crc = CalcCRC(buffer, index); 124 | buffer[index++] = (crc >> 8) & 0xFF; 125 | buffer[index++] = crc & 0xFF; 126 | 127 | // Stop byte 128 | buffer[index++] = '\n'; 129 | 130 | SendBuffer(buffer, index); 131 | } 132 | 133 | //---------------------------------------------------------------------------- 134 | // Calculates CRC value 135 | //---------------------------------------------------------------------------- 136 | uint16_t CalcCRC(uint8_t *ptr, int count) 137 | { 138 | uint16_t crc; 139 | uint8_t i; 140 | crc = 0; 141 | while (--count >= 0) 142 | { 143 | crc = crc ^ (uint16_t) *ptr++ << 8; 144 | i = 8; 145 | do 146 | { 147 | if (crc & 0x8000) 148 | { 149 | crc = crc << 1 ^ 0x1021; 150 | } 151 | else 152 | { 153 | crc = crc << 1; 154 | } 155 | } while(--i); 156 | } 157 | return (crc); 158 | } 159 | 160 | //---------------------------------------------------------------------------- 161 | // Sends buffer 162 | //---------------------------------------------------------------------------- 163 | void SendBuffer(uint8_t buffer[], uint8_t length) 164 | { 165 | uint8_t index = 0; 166 | 167 | for(; index < length; index++) 168 | { 169 | Serial.write(buffer[index]); 170 | } 171 | } 172 | 173 | //---------------------------------------------------------------------------- 174 | // Sends debug infos 175 | //---------------------------------------------------------------------------- 176 | void SendDebug() 177 | { 178 | Serial.print(speedValue); 179 | Serial.print(","); 180 | Serial.println(steerValue); 181 | } 182 | -------------------------------------------------------------------------------- /PPMDeviceArduino_V1.0/PPMDevice/SteeringSerial.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef STEERINGSERIAL_H 32 | #define STEERINGSERIAL_H 33 | 34 | #include 35 | #include 36 | #include "utils.h" 37 | 38 | //---------------------------------------------------------------------------- 39 | // Initializes the steering serial 40 | //---------------------------------------------------------------------------- 41 | void InitSteeringSerial(void); 42 | 43 | //---------------------------------------------------------------------------- 44 | // Sets the speed value 45 | //---------------------------------------------------------------------------- 46 | void SetSpeed(uint16_t data, float factor); 47 | 48 | //---------------------------------------------------------------------------- 49 | // Sets the steering value 50 | //---------------------------------------------------------------------------- 51 | void SetSteer(uint16_t data); 52 | 53 | //---------------------------------------------------------------------------- 54 | // Sends answer to master device 55 | //---------------------------------------------------------------------------- 56 | void SendAnswer(void); 57 | 58 | 59 | //---------------------------------------------------------------------------- 60 | // Sends debug infos 61 | //---------------------------------------------------------------------------- 62 | void SendDebug(); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /PPMDeviceArduino_V1.0/PPMDevice/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the hoverboard-firmware-hack-V2 project. The 3 | * firmware is used to hack the generation 2 board of the hoverboard. 4 | * These new hoverboards have no mainboard anymore. They consist of 5 | * two Sensorboards which have their own BLDC-Bridge per Motor and an 6 | * ARM Cortex-M3 processor GD32F130C8. 7 | * 8 | * Copyright (C) 2018 Florian Staeblein 9 | * Copyright (C) 2018 Jakob Broemauer 10 | * Copyright (C) 2018 Kai Liebich 11 | * Copyright (C) 2018 Christoph Lehnert 12 | * 13 | * The program is based on the hoverboard project by Niklas Fauth. The 14 | * structure was tried to be as similar as possible, so that everyone 15 | * could find a better way through the code. 16 | * 17 | * This program is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | */ 30 | 31 | #ifndef UTILS_H 32 | #define UTILS_H 33 | 34 | #define ABS(a) (((a) < 0.0) ? -(a) : (a)) 35 | #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) 36 | #define MAP(x, xMin, xMax, yMin, yMax) ((x - xMin) * (yMax - yMin) / (xMax - xMin) + yMin) 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### Updates: 2 | ```` 3 | - Firmware is ready. 4 | - Sadly I can not support any issues. I'm not a student, less free time :) 5 | ```` 6 | 7 | ### Hoverboard-Firmware-Hack-Gen2 8 | 9 | Hoverboard Hack Firmware Generation 2 for the Hoverboard with the two Mainboards instead of the Sensorboards (See Pictures). 10 | 11 | This repo contains open source firmware for generic Hoverboards with two mainboards. It allows you to control the hardware of the new version of hoverboards (like the Mainboard, Motors and Battery) with an arduino or some other steering device for projects like driving armchairs. 12 | 13 | The structure of the firmware is based on the firmware hack of Niklas Fauth (https://github.com/NiklasFauth/hoverboard-firmware-hack/). Because of a different model of processor (GD32F130C8 instead of STM32F103) it was not possible to use the same firmware and it has to be written from scratch (Different hardware, different, pins, different registers :( ) 14 | 15 | - This project requires knowledge of the initial project linked above. 16 | - At the current point I am not able to support any questions or issues - sorry! 17 | 18 | --- 19 | 20 | #### Hardware 21 | ![otter](https://github.com/flo199213/Hoverboard-Firmware-Hack-Gen2/blob/master/Hardware_Overview_small.png) 22 | 23 | The hardware has two main boards, which are different equipped. They are connected via USART. Additionally there are some LED PCB connected at X1 and X2 which signalize the battery state and the error state. There is an programming connector for ST-Link/V2 and they break out GND, USART/I2C, 5V on a second pinhead. 24 | 25 | The reverse-engineered schematics of the mainboards can be found here: 26 | https://github.com/flo199213/Hoverboard-Firmware-Hack-Gen2/blob/master/Schematics/HoverBoard_CoolAndFun.pdf 27 | 28 | 29 | --- 30 | 31 | #### Flashing 32 | The firmware is built with Keil (free up to 32KByte). To build the firmware, open the Keil project file which is includes in repository. Right to the STM32, there is a debugging header with GND, 3V3, SWDIO and SWCLK. Connect GND, SWDIO and SWCLK to your SWD programmer, like the ST-Link found on many STM devboards. 33 | 34 | - If you never flashed your mainboard before, the controller is locked. To unlock the flash, use STM32 ST-LINK Utility or openOCD. 35 | - To flash the STM32, use the STM32 ST-LINK Utility as well, ST-Flash utility or Keil by itself. 36 | - Hold the powerbutton while flashing the firmware, as the controller releases the power latch and switches itself off during flashing 37 | -------------------------------------------------------------------------------- /Raumzeigerdiagramm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flo199213/Hoverboard-Firmware-Hack-Gen2/e138b221aed944478d12e15d81fb858f44f4a289/Raumzeigerdiagramm.png -------------------------------------------------------------------------------- /Schematics/HoverBoard_CoolAndFun.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flo199213/Hoverboard-Firmware-Hack-Gen2/e138b221aed944478d12e15d81fb858f44f4a289/Schematics/HoverBoard_CoolAndFun.pdf --------------------------------------------------------------------------------