x-nucleo-6180xa1.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. /*
  2. * @file x-nucleo-6180xa1.c
  3. * $Date: 2015-10-21 16:55:39 +0200 (Wed, 21 Oct 2015) $
  4. * $Revision: 2560 $
  5. */
  6. #include <string.h>
  7. /** Configure VL6180 pins to Output */
  8. #include "stm32xxx_hal.h"
  9. #ifndef HAL_I2C_MODULE_ENABLED
  10. #define HAL_I2C_MODULE_ENABLED
  11. #pragma message("hal conf should enable i2c")
  12. #endif
  13. #include "x-nucleo-6180xa1.h"
  14. #define V1_CHIP_SWITCH_PORT GPIOA
  15. #define V1_CHIP_SWITCH_PIN GPIO_PIN_7
  16. #define V1_CHIP_ENABLE_PORT GPIOA
  17. #define V1_CHIP_ENABLE_PIN GPIO_PIN_5
  18. #define V1_IRQ_PIN GPIO_PIN_6
  19. #define V2_IRQ_PIN GPIO_PIN_0
  20. #ifdef __STM32F4xx_HAL_H
  21. #define V1_IRQ EXTI9_5_IRQn
  22. #define V2_IRQ EXTI0_IRQn
  23. #else
  24. #ifdef __STM32L4xx_HAL_H
  25. #define V1_IRQ EXTI9_5_IRQn
  26. #define V2_IRQ EXTI0_IRQn
  27. #else
  28. #define V1_IRQ EXTI4_15_IRQn
  29. #define V2_IRQ EXTI0_1_IRQn
  30. #endif
  31. #endif
  32. /* local private prototypes */
  33. static void _V1_GPIO_Init(void);
  34. static void _V1_Set7SegmentDP( int dp);
  35. static void _V1_Set7Segment(uint8_t value);
  36. static void _V1_DisplayOff(void);
  37. static void _V2_GPIO_Init(void);
  38. static int _V2_GetSwicth(void);
  39. #define EXPANDER_I2C_ADDRESS (0x42*2)
  40. #define GPMR 0x10
  41. #define GPSR 0x12
  42. #define GPDR 0x14
  43. #define V2_D1 (1<<7)
  44. // second byte or word MSB
  45. #define V2_D2 (1<<8)
  46. #define V2_D3 (1<<9)
  47. #define V2_D4 (1<<10)
  48. #define V2_DISP_SEL (1<<11)
  49. #define V2_CHIPEN (1<<12)
  50. #define V2_CHIPEN_B (1<<13)
  51. #define V2_CHIPEN_L (1<<14)
  52. #define V2_CHIPEN_R (1<<15)
  53. static int IsV2=0;
  54. I2C_HandleTypeDef *_hi2c;
  55. uint16_t _V2PadVal; /* gpio SR value caching to avoid reading on each new bit set */
  56. static int I2cExpAddr=EXPANDER_I2C_ADDRESS;
  57. static int _err=0;
  58. static void _V2_DisplayOff(void);
  59. static void _V2_SetChipEn( int No, int state );
  60. int XNUCLEO6180XA1_IsV2(void){
  61. return IsV2;
  62. }
  63. int XNUCLEO6180XA1_EXTI_CallBackHandle(uint16_t GPIO_Pin){
  64. int IsVL6180XIntPin = IsV2 ? GPIO_Pin == V2_IRQ_PIN : GPIO_Pin == V1_IRQ_PIN;
  65. if( IsVL6180XIntPin){
  66. XNUCLEO6180XA1_UserIntHandler();
  67. }
  68. return IsVL6180XIntPin;
  69. }
  70. void XNUCLEO6180XA1_Reset(int state){
  71. if( !IsV2)
  72. HAL_GPIO_WritePin(V1_CHIP_ENABLE_PORT, V1_CHIP_ENABLE_PIN , (GPIO_PinState)state);
  73. else{
  74. _V2_SetChipEn(0, state);
  75. }
  76. }
  77. int XNUCLEO6180XA1_ResetId(int state, int id)
  78. {
  79. int status;
  80. if( IsV2 && id>=0 && id<4){
  81. _V2_SetChipEn(id, state);
  82. status=0;
  83. }
  84. else{
  85. /* Error case */
  86. status=-1;
  87. }
  88. return status;
  89. }
  90. int XNUCLEO6180XA1_GetSwitch(void){
  91. GPIO_PinState state ;
  92. if( !IsV2)
  93. state = HAL_GPIO_ReadPin(V1_CHIP_SWITCH_PORT, V1_CHIP_SWITCH_PIN);
  94. else{
  95. state= _V2_GetSwicth() ? GPIO_PIN_SET : GPIO_PIN_RESET ;
  96. }
  97. return state;
  98. }
  99. /* public API */
  100. void XNUCLEO6180XA1_GPIO_Init(void) {
  101. // this must be done after i2c init _V1_GPIO_Init();
  102. }
  103. int V2_ExpanderRd(int index, uint8_t *data, int n_data){
  104. int status;
  105. uint8_t RegAddr;
  106. RegAddr=index;
  107. do{
  108. status=HAL_I2C_Master_Transmit(_hi2c, I2cExpAddr, &RegAddr, 1, 100);
  109. if( status )
  110. break;
  111. status =HAL_I2C_Master_Receive(_hi2c, I2cExpAddr, data, n_data, n_data*100);
  112. }while(0);
  113. return status;
  114. }
  115. int V2_ExpanderWR( int index, uint8_t *data, int n_data){
  116. int status;
  117. uint8_t RegAddr[0x10];
  118. RegAddr[0]=index;
  119. memcpy(RegAddr+1, data, n_data);
  120. status=HAL_I2C_Master_Transmit(_hi2c, I2cExpAddr, RegAddr, n_data+1, 100);
  121. return status;
  122. }
  123. /**
  124. *
  125. * @param No 0= top , 1= Left, 2=Bottom 3=Right
  126. * @param state
  127. */
  128. static void _V2_SetChipEn( int No, int state ){
  129. //int mask = V2_CHIPEN << No;
  130. int mask = (No==3) ? V2_CHIPEN_R : ((No==2) ? V2_CHIPEN_B : ((No==1) ? V2_CHIPEN_L : V2_CHIPEN));
  131. if( state)
  132. _V2PadVal|=mask ;
  133. else
  134. _V2PadVal&=~mask;
  135. V2_ExpanderWR(GPSR, (uint8_t*)&_V2PadVal,2);
  136. }
  137. int _V2_GetSwicth(){
  138. int status;
  139. uint16_t Value;
  140. status=V2_ExpanderRd(GPMR, (uint8_t*)&Value,2);
  141. if(status ==0 ){
  142. Value&=V2_DISP_SEL;
  143. }
  144. else{
  145. //TODO ("VL6180x Expander rd fail");
  146. _err++;
  147. Value=0;
  148. }
  149. return Value;
  150. }
  151. static void _I2cFailRecover(){
  152. GPIO_InitTypeDef GPIO_InitStruct;
  153. int i, nRetry=0;
  154. // We may get reset after in middle of an i2c access (h/w reset button use or debug load)
  155. // hence some agent on bus may be in middle of a a transaction and will create issue or even prevent starting (SDA is low)
  156. // We can't assume bus state based on SDA and SCL state (we may be in a data or NAk bit so SCL=SDA=1)
  157. // by setting SDA high and toggling SCL at least 10 time we ensure whatever agent and state
  158. // all agent will end up seeing a "stop" end bus we back to an known idle i2c bus state
  159. // Enable I/O
  160. __GPIOB_CLK_ENABLE();
  161. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
  162. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
  163. GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9 ;
  164. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  165. GPIO_InitStruct.Pull = GPIO_PULLUP;
  166. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  167. //TODO we could do this faster by not using HAL delay 1ms for clk timing
  168. do{
  169. for( i=0; i<10; i++){
  170. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
  171. HAL_Delay(1);
  172. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
  173. HAL_Delay(1);
  174. }
  175. // if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 ){
  176. // static int RetryRecover;
  177. // RetryRecover++;
  178. // }
  179. }while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 && nRetry++<7);
  180. if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 ){
  181. __GPIOA_CLK_ENABLE();
  182. //We are still in bad i2c state warm user by blinking led but stay here
  183. GPIO_InitStruct.Pin = GPIO_PIN_5 ;
  184. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  185. GPIO_InitStruct.Pull = GPIO_NOPULL;
  186. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  187. do{
  188. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
  189. HAL_Delay(33);
  190. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
  191. HAL_Delay(33);
  192. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
  193. HAL_Delay(33);
  194. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
  195. HAL_Delay(33*20);
  196. }while(1);
  197. }
  198. }
  199. /**
  200. * F401 valid may not work for over device
  201. */
  202. void XNUCLEO6180XA1_I2C1_Init(I2C_HandleTypeDef *hi2c1) {
  203. GPIO_InitTypeDef GPIO_InitStruct;
  204. uint8_t ExpanderID[2];
  205. int status;
  206. _I2cFailRecover();
  207. /* Peripheral clock enable */
  208. __GPIOB_CLK_ENABLE();
  209. __I2C1_CLK_ENABLE();
  210. /**I2C1 GPIO Configuration
  211. PB8 ------> I2C1_SCL
  212. PB9 ------> I2C1_SDA
  213. */
  214. GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
  215. GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
  216. GPIO_InitStruct.Pull = GPIO_PULLUP;
  217. GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  218. GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
  219. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  220. hi2c1->Instance = I2C1;
  221. #ifdef __STM32F4xx_HAL_H
  222. hi2c1->Init.ClockSpeed = 400000;
  223. hi2c1->Init.DutyCycle = I2C_DUTYCYCLE_2;
  224. #else
  225. hi2c1->Init.Timing = 0x00300F38; /* set 400KHz fast mode i2c*/
  226. #endif
  227. hi2c1->Init.OwnAddress1 = 0;
  228. hi2c1->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  229. hi2c1->Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
  230. hi2c1->Init.OwnAddress2 = 0;
  231. hi2c1->Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
  232. hi2c1->Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
  233. HAL_I2C_Init(hi2c1);
  234. /* try to detect v1 v2 by reading i2c expander register
  235. * if rd i2c fail assume it is a v1 shield it may be a v2 with an i2c bus hangs (happen some time)*/
  236. _hi2c=hi2c1;
  237. status = V2_ExpanderRd( 0, ExpanderID, 2);
  238. if( status == 0 && ExpanderID[0]==0 && ExpanderID[1]==0x16){
  239. IsV2=1;
  240. _V2_GPIO_Init();
  241. }
  242. else{
  243. _V1_GPIO_Init();
  244. }
  245. }
  246. /**
  247. * @brief Default do nothing interrupt callback
  248. */
  249. #pragma weak XNUCLEO6180XA1_UserIntHandler
  250. void XNUCLEO6180XA1_UserIntHandler(void) {
  251. }
  252. void XNUCLEO6180XA1_ClearInterrupt(void){
  253. if( !IsV2 )
  254. NVIC_ClearPendingIRQ(V1_IRQ);
  255. else
  256. NVIC_ClearPendingIRQ(V2_IRQ);
  257. }
  258. void XNUCLEO6180XA1_DisableInterrupt(void){
  259. if( !IsV2){
  260. HAL_NVIC_DisableIRQ(V1_IRQ);
  261. __HAL_GPIO_EXTI_CLEAR_IT(V1_IRQ_PIN);
  262. NVIC_ClearPendingIRQ(V1_IRQ);
  263. }
  264. else{
  265. HAL_NVIC_DisableIRQ(V2_IRQ);
  266. __HAL_GPIO_EXTI_CLEAR_IT(V2_IRQ_PIN);
  267. NVIC_ClearPendingIRQ(V2_IRQ);
  268. }
  269. }
  270. void XNUCLEO6180XA1_EnableInterrupt(void){
  271. if( !IsV2 ){
  272. __HAL_GPIO_EXTI_CLEAR_IT(V1_IRQ_PIN);
  273. NVIC_ClearPendingIRQ(V1_IRQ);
  274. HAL_NVIC_EnableIRQ(V1_IRQ);
  275. }
  276. else{
  277. __HAL_GPIO_EXTI_CLEAR_IT(V2_IRQ_PIN);
  278. NVIC_ClearPendingIRQ(V2_IRQ);
  279. HAL_NVIC_EnableIRQ(V2_IRQ);
  280. }
  281. }
  282. /**
  283. * Display digit enable pad/pin LUT
  284. * D1 is left most digit (ms nibble) on the display
  285. * D3 is right most digit (ls nibble) on the display
  286. */
  287. #define PA 0
  288. #define PB 1
  289. #define PC 2
  290. #define MAKE_PAD(port, pin) (((port)<<4)|pin)
  291. /* digit enable pad/pin LUT */
  292. static uint8_t DisplayEn[] = {
  293. MAKE_PAD( PB, 0), /* D1 0 */
  294. MAKE_PAD( PA, 4), /* D2 1 */
  295. MAKE_PAD( PA, 1), /* D3 2 */
  296. MAKE_PAD( PA, 0), /* D4 3 */
  297. };
  298. /* 7 segment code to pad/pin LUT */
  299. static uint8_t DisplaySeg[] = {
  300. MAKE_PAD( PB, 6 ), /* 0 A */
  301. MAKE_PAD( PC, 7 ), /* 1 B */
  302. MAKE_PAD( PA, 9 ), /* 2 C */
  303. MAKE_PAD( PA, 8 ), /* 3 D */
  304. MAKE_PAD( PB, 10), /* 4 E */
  305. MAKE_PAD( PB, 4 ), /* 5 F */
  306. MAKE_PAD( PB, 5 ), /* 6 G */
  307. MAKE_PAD( PB, 3 ), /* 7 DP */
  308. /* Note that PB3 these is conflicting wit jtag/SWO used for trace
  309. * activating PB3 as ooutput will prevent trace to work */
  310. };
  311. #undef MAKE_PAD
  312. #undef PA
  313. #undef PB
  314. #undef PC
  315. #define pad_write(pad, state) HAL_GPIO_WritePin( (GPIO_TypeDef*)((char*)GPIOA + (pad>>4)*((char*)GPIOB-(char*)GPIOA)), 1<<(pad&0x0F), state);
  316. /*
  317. --s0--
  318. s s
  319. 5 1
  320. --s6--
  321. s s
  322. 4 2
  323. --s3-- s7
  324. */
  325. #define DP (1<<7)
  326. #define NOT_7_NO_DP( ... ) (uint8_t) ~( __VA_ARGS__ + DP )
  327. #define S0 (1<<0)
  328. #define S1 (1<<1)
  329. #define S2 (1<<2)
  330. #define S3 (1<<3)
  331. #define S4 (1<<4)
  332. #define S5 (1<<5)
  333. #define S6 (1<<6)
  334. /* refer to http://www.twyman.org.uk/Fonts/ */
  335. static const uint8_t ascii_to_display_lut[256]={
  336. [' ']= 0,
  337. ['-']= S6,
  338. ['_']= S3,
  339. ['=']= S3+S6,
  340. ['~']= S0+S3+S6, /* 3 h bar */
  341. ['^']= S0, /* use as top bar */
  342. ['?']= NOT_7_NO_DP(S5+S3+S2),
  343. ['*']= NOT_7_NO_DP(),
  344. ['[']= S0+S3+S4+S5,
  345. [']']= S0+S3+S2+S1,
  346. ['@']= S0+S3,
  347. ['0']= NOT_7_NO_DP(S6),
  348. ['1']= S1+S2,
  349. ['2']= S0+S1+S6+S4+S3,
  350. ['3']= NOT_7_NO_DP(S4+S5),
  351. ['4']= S5+S1+S6+S2,
  352. ['5']= NOT_7_NO_DP(S1+S4),
  353. ['6']= NOT_7_NO_DP(S1),
  354. ['7']= S0+S1+S2,
  355. ['8']= NOT_7_NO_DP(0),
  356. ['9']= NOT_7_NO_DP(S4),
  357. ['a']= S2+ S3+ S4+ S6 ,
  358. ['b']= NOT_7_NO_DP(S0+S1),
  359. ['c']= S6+S4+S3,
  360. ['d']= NOT_7_NO_DP(S0+S5),
  361. ['e']= NOT_7_NO_DP(S2),
  362. ['f']= S6+S5+S4+S0, /* same as F */
  363. ['g']= NOT_7_NO_DP(S4), /* same as 9 */
  364. ['h']= S6+S5+S4+S2,
  365. ['i']= S4,
  366. ['j']= S1+S2+S3+S4,
  367. ['k']= S6+S5+S4+S2, /* a h */
  368. ['l']= S3+S4,
  369. ['m']= S0+S4+S2, /* same as */
  370. ['n']= S2+S4+S6,
  371. ['o']= S6+S4+S3+S2,
  372. ['p']= NOT_7_NO_DP(S3+S2), // same as P
  373. ['q']= S0+S1+S2+S5+S6,
  374. ['r']= S4+S6,
  375. ['s']= NOT_7_NO_DP(S1+S4),
  376. ['t']= NOT_7_NO_DP(S0+S1+S2),
  377. ['u']= S4+S3+S2+S5+S1, // U
  378. ['v']= S4+S3+S2, // is u but u use U
  379. ['w']= S1+S3+S5,
  380. ['x']= NOT_7_NO_DP(S0+S3), // similar to H
  381. ['y']= NOT_7_NO_DP(S0+S4),
  382. ['z']= S0+S1+S6+S4+S3, // same as 2
  383. ['A']= NOT_7_NO_DP(S3),
  384. ['B']= NOT_7_NO_DP(S0+S1), /* as b */
  385. ['C']= S0+S3+S4+S5, // same as [
  386. ['E']= NOT_7_NO_DP(S1+S2),
  387. ['F']= S6+S5+S4+S0,
  388. ['G']= NOT_7_NO_DP(S4), /* same as 9 */
  389. ['H']= NOT_7_NO_DP(S0+S3),
  390. ['I']= S1+S2,
  391. ['J']= S1+S2+S3+S4,
  392. ['K']= NOT_7_NO_DP(S0+S3), /* same as H */
  393. ['L']= S3+S4+S5,
  394. ['M']= S0+S4+S2, /* same as m*/
  395. ['N']= S2+S4+S6, /* same as n*/
  396. ['O']= NOT_7_NO_DP(S6),
  397. ['P']= S0+S1+S2+S5+S6, // sames as 'q'
  398. ['Q']= NOT_7_NO_DP(S3+S2),
  399. ['R']= S4+S6,
  400. ['S']= NOT_7_NO_DP(S1+S4), /* sasme as 5 */
  401. ['T']= NOT_7_NO_DP(S0+S1+S2), /* sasme as t */
  402. ['U']= NOT_7_NO_DP(S6+S0),
  403. ['V']= S4+S3+S2, // is u but u use U
  404. ['W']= S1+S3+S5,
  405. ['X']= NOT_7_NO_DP(S0+S3), // similar to H
  406. ['Y']= NOT_7_NO_DP(S0+S4),
  407. ['Z']= S0+S1+S6+S4+S3, // same as 2
  408. };
  409. #undef S0
  410. #undef S1
  411. #undef S2
  412. #undef S3
  413. #undef S4
  414. #undef S5
  415. #undef S6
  416. #undef DP
  417. static void _V1_DisplayString(const char *str, int SegDelayMs){
  418. int i;
  419. const char *pc;
  420. for( i=0, pc=str; i<4 && *pc!=0 ; i++, pc++){
  421. _V1_Set7Segment( ascii_to_display_lut[(uint8_t)*pc]);
  422. if( *(pc+1)== '.'){
  423. _V1_Set7SegmentDP(1);
  424. pc++;
  425. }
  426. /* digit on */
  427. pad_write(DisplayEn[i], GPIO_PIN_RESET); /* activate led */
  428. XNUCLEO6180XA1_WaitMilliSec(SegDelayMs);
  429. /* digit off */
  430. pad_write(DisplayEn[i], GPIO_PIN_SET); /* turn off led */
  431. }
  432. }
  433. static void _V2_Set7Segment( int Leds, int digit ){
  434. _V2PadVal |= 0x7F; /* clear 7 seg bits */
  435. _V2PadVal |= V2_D1|V2_D2|V2_D3|V2_D4; /* all segment off */
  436. _V2PadVal &= ~(V2_D1<<digit); /* digit on */
  437. _V2PadVal &= ~(Leds&0x7F);
  438. V2_ExpanderWR(GPSR, (uint8_t*)&_V2PadVal, 2);
  439. }
  440. static void _V2_DisplayString(const char *str, int SegDelayMs){
  441. int i;
  442. const char *pc;
  443. for( i=0, pc=str; i<4 && *pc!=0 ; i++, pc++){
  444. _V2_Set7Segment( ascii_to_display_lut[(uint8_t)*pc], i);
  445. if( *(pc+1)== '.'){
  446. pc++;
  447. }
  448. XNUCLEO6180XA1_WaitMilliSec(SegDelayMs);
  449. _V2_DisplayOff();
  450. }
  451. }
  452. /**
  453. * accept . on any digit
  454. */
  455. void XNUCLEO6180XA1_DisplayString(const char *str, int SegDelayMs){
  456. if( !IsV2)
  457. _V1_DisplayString(str, SegDelayMs);
  458. else
  459. _V2_DisplayString(str, SegDelayMs);
  460. }
  461. static void _V1_GPIO_Init(void) {
  462. GPIO_InitTypeDef GPIO_InitStruct;
  463. /* GPIO Ports Clock Enable */
  464. __GPIOC_CLK_ENABLE();
  465. __GPIOH_CLK_ENABLE();
  466. __GPIOA_CLK_ENABLE();
  467. __GPIOB_CLK_ENABLE();
  468. /*Configure GPIO pins : PA0 PA1 PA4 PA5 PA8 PA9 */
  469. GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_9;
  470. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  471. GPIO_InitStruct.Pull = GPIO_NOPULL;
  472. GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  473. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  474. /*Configure GPIO pins : PA7 select */
  475. GPIO_InitStruct.Pin = GPIO_PIN_7;
  476. GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  477. GPIO_InitStruct.Pull = GPIO_NOPULL;
  478. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  479. /*Configure GPIO pins : PA6 interrupt */
  480. GPIO_InitStruct.Pin = GPIO_PIN_6;
  481. GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  482. GPIO_InitStruct.Pull = GPIO_NOPULL;
  483. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  484. /*Configure GPIO pins : PB0 PB10 PB3 PB4 PB5 PB6 */
  485. GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_10 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
  486. #ifndef OS_USE_TRACE_ITM
  487. GPIO_InitStruct.Pin |= GPIO_PIN_3;
  488. #endif
  489. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  490. GPIO_InitStruct.Pull = GPIO_NOPULL;
  491. GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  492. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  493. /*Configure GPIO pin : PC7 7 segment B */
  494. GPIO_InitStruct.Pin = GPIO_PIN_7;
  495. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  496. GPIO_InitStruct.Pull = GPIO_NOPULL;
  497. GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  498. HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  499. /* turn off all 7 seg digit */
  500. _V1_DisplayOff();
  501. }
  502. static void _V2_GPIO_Init(){
  503. uint16_t PadDir;
  504. GPIO_InitTypeDef GPIO_InitStruct;
  505. __GPIOA_CLK_ENABLE();
  506. __GPIOB_CLK_ENABLE();
  507. /*Configure GPIO pins interrupt PA4 = INTB , PA5 = INTL, pA10 = INTR */
  508. GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 |GPIO_PIN_10 ;
  509. GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  510. GPIO_InitStruct.Pull = GPIO_NOPULL;
  511. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  512. /* PB0 = INT */
  513. GPIO_InitStruct.Pin = GPIO_PIN_0;
  514. GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  515. GPIO_InitStruct.Pull = GPIO_NOPULL;
  516. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  517. /* expender config */
  518. PadDir=~V2_DISP_SEL;
  519. V2_ExpanderWR(GPDR, (uint8_t*)&PadDir, 2);
  520. _V2_DisplayOff();
  521. }
  522. static void _V2_DisplayOff() {
  523. _V2PadVal |= (V2_D1|V2_D2|V2_D3| V2_D4); /* segment en off */
  524. V2_ExpanderWR(GPSR, (uint8_t*)&_V2PadVal, 2);
  525. }
  526. static void _V1_DisplayOff() {
  527. int i;
  528. for( i=0; i<4; i++ ){
  529. pad_write(DisplayEn[i], GPIO_PIN_SET); /* turn off led */
  530. }
  531. }
  532. /* set 7 segment bus to display decode "value" */
  533. static void _V1_Set7Segment(const uint8_t value) {
  534. int i;
  535. GPIO_PinState state;
  536. for (i = 0; i < sizeof(DisplaySeg)/sizeof(DisplaySeg[0]); i++) {
  537. int cur_bit;
  538. cur_bit = value & (1 << i);
  539. state = cur_bit ? GPIO_PIN_RESET: GPIO_PIN_SET; /* port clear= segment on */
  540. pad_write(DisplaySeg[i], state);
  541. }
  542. }
  543. /* set state of decimal point on 7 segment bus */
  544. static void _V1_Set7SegmentDP( int dp_state) {
  545. GPIO_PinState state;
  546. state = dp_state ? GPIO_PIN_RESET: GPIO_PIN_SET; // port clear= segment on
  547. pad_write(DisplaySeg[7], state);
  548. //HAL_GPIO_WritePin((void*)GPIOA + DisplaySeg[7].port*((void*)GPIOB-(void*)GPIOA), 1<<DisplaySeg[7].pin, state);
  549. }