5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
23 #define CS1_HIGH() TOPLCD_GPIO->BSRRL = TOPLCD_GPIO_PIN_CS1
24 #define CS1_LOW() TOPLCD_GPIO->BSRRH = TOPLCD_GPIO_PIN_CS1
25 #define CS2_HIGH() TOPLCD_GPIO->BSRRL = TOPLCD_GPIO_PIN_CS2
26 #define CS2_LOW() TOPLCD_GPIO->BSRRH = TOPLCD_GPIO_PIN_CS2
27 #define WR_HIGH() TOPLCD_GPIO->BSRRL = TOPLCD_GPIO_PIN_WR
28 #define WR_LOW() TOPLCD_GPIO->BSRRH = TOPLCD_GPIO_PIN_WR
29 #define DATA_HIGH() TOPLCD_GPIO->BSRRL = TOPLCD_GPIO_PIN_DATA
30 #define DATA_LOW() TOPLCD_GPIO->BSRRH = TOPLCD_GPIO_PIN_DATA
31 #define BL_ON() TOPLCD_GPIO->BSRRL = TOPLCD_GPIO_PIN_BL
32 #define BL_OFF() TOPLCD_GPIO->BSRRH = TOPLCD_GPIO_PIN_BL
34 const uint8_t TimeLCDsegs
[] = { 0xAF, 0x06, 0x6D, 0x4F, 0xC6, 0xCB, 0xEB, 0x0E, 0xEF, 0xCF };
35 const uint8_t RssiLCDsegs
[] = { 0xFA, 0x60, 0xBC, 0xF4, 0x66, 0xD6, 0xDE, 0x70, 0xFE, 0xF6 };
36 const uint8_t OpTimeLCDsegs
[] = { 0x5F, 0x06, 0x6B, 0x2F, 0x36, 0x3D, 0x7D, 0x07, 0x7F, 0x3F };
38 uint8_t Ht1621Data1
[11] = { 0 };
39 uint8_t Ht1621Data2
[7] = { 0 };
46 void ht1621SendCommand(uint8_t chip
, unsigned char command
)
54 WR_LOW(); //PRESENT 100 COMMAND CODE
74 for (int i
=0; i
<8; i
++) {
77 if ((command
& 0x80) !=0) {
87 command
= command
<< 1;
102 void ht1621WrData(uint8_t data
, uint8_t count
)
118 void ht1621WrAllData(uint8_t chip
, uint8_t *pData
)
122 len
= sizeof(Ht1621Data2
);
126 len
= sizeof(Ht1621Data1
);
130 ht1621WrData(0xa0, 3);
131 ht1621WrData(0, 6); // HT1621 6 bit,left 2 bit;
132 for (int i
=0; i
<len
; i
++) {
133 ht1621WrData(*pData
++, 8);
143 void initTimerTopLcd()
146 RCC
->APB1ENR
|= RCC_APB1ENR_TIM12EN
; // Enable clock
147 TIM12
->ARR
= 17; // 1.7uS
148 TIM12
->PSC
= (PERI1_FREQUENCY
* TIMER_MULT_APB1
) / 10000000 - 1; // 0.1uS from 30MHz
154 NVIC_SetPriority(TIM8_BRK_TIM12_IRQn
, 2 );
155 NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn
);
158 extern "C" void TIM8_BRK_TIM12_IRQHandler()
160 struct t_top_lcd_control
*pc
;
161 TIM12
->SR
&= ~TIM_SR_UIF
;
164 if ( pc
->state
== TOP_LCD_CKLOW
) {
165 WR_LOW(); //PRESENT 100 COMMAND CODE
166 if ((*pc
->data
& 0x80) !=0) {
173 pc
->state
= TOP_LCD_CKHI
;
175 else if ( pc
->state
== TOP_LCD_CKHI
) {
177 if ( --pc
->count
== 0 ) {
178 pc
->state
= TOP_LCD_END
;
181 pc
->state
= TOP_LCD_CKLOW
;
184 else if (pc
->state
== TOP_LCD_END
) {
187 pc
->state
= TOP_LCD_IDLE
;
193 pc
->data
= pc
->data2
;
194 pc
->count
= pc
->count2
;
195 pc
->state
= TOP_LCD_IDLE
;
198 else if ( pc
->state
== TOP_LCD_IDLE
) {
200 if ( pc
->chip
) CS2_LOW(); else CS1_LOW();
201 pc
->state
= TOP_LCD_1CKLOW
;
203 else if ( pc
->state
== TOP_LCD_1CKLOW
) {
205 DATA_HIGH(); // First 1 bit
206 pc
->state
= TOP_LCD_1CKHI
;
208 else if ( pc
->state
== TOP_LCD_1CKHI
) {
210 if ( --pc
->count
== 0 ) {
211 pc
->state
= TOP_LCD_END
;
214 pc
->state
= TOP_LCD_CKLOW
;
222 RCC_AHB1PeriphClockCmd(TOPLCD_RCC_AHB1Periph
, ENABLE
);
223 GPIO_InitTypeDef GPIO_InitStructure
;
224 GPIO_InitStructure
.GPIO_Pin
= TOPLCD_GPIO_PIN_DATA
| TOPLCD_GPIO_PIN_WR
|TOPLCD_GPIO_PIN_BL
|TOPLCD_GPIO_PIN_CS1
|TOPLCD_GPIO_PIN_CS2
;
225 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_OUT
;
226 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
227 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_2MHz
;
228 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_UP
;
229 GPIO_Init(TOPLCD_GPIO
, &GPIO_InitStructure
);
233 ht1621SendCommand(0, 0x03);
234 ht1621SendCommand(0, 0x01);
235 ht1621SendCommand(0, 0x29);
237 ht1621SendCommand(1, 0x03);
238 ht1621SendCommand(1, 0x01);
239 ht1621SendCommand(1, 0x29);
241 toplcdRefreshStart();
248 toplcdRefreshStart();
252 void setTopFirstTimer(int32_t value
)
254 Ht1621Data1
[2] |= 0x10; // ":"
257 if (BLINK_ON_PHASE
) {
265 div_t qr
= div((int)value
, 60);
267 qr
= div(qr
.quot
, 10);
269 // Limit to 99 min 99 sec to avoid breaking display
276 Ht1621Data1
[0] |= TimeLCDsegs
[qr
.quot
];
277 Ht1621Data1
[1] |= TimeLCDsegs
[qr
.rem
];
279 Ht1621Data1
[2] |= TimeLCDsegs
[qr
.quot
];
280 Ht1621Data1
[3] |= TimeLCDsegs
[qr
.rem
];
283 void setTopRssiValue(uint32_t rssi
)
285 div_t qr
= div(rssi
, 10);
291 Ht1621Data2
[2] |= r
? RssiLCDsegs
[1] : 0;
292 Ht1621Data2
[1] |= (r
|| qr
.quot
) ? RssiLCDsegs
[qr
.quot
] : 0;
293 Ht1621Data2
[0] |= RssiLCDsegs
[qr
.rem
];
296 void setTopRssiBar(uint32_t rssi
)
305 Ht1621Data2
[3] |= 0x10;
307 Ht1621Data2
[3] |= 0x20;
309 Ht1621Data2
[3] |= 0x40;
311 Ht1621Data2
[3] |= 0x80;
314 void setTopRssi(uint32_t rssi
)
316 Ht1621Data1
[4] |= 0x10; // "RSSI"
317 Ht1621Data2
[3] |= 0x01; // "dB"
318 Ht1621Data2
[4] |= 0x01; // Horizontal line
319 setTopRssiValue(rssi
);
323 void setTopBatteryState(int state
, uint8_t blinking
)
325 if (!blinking
|| BLINK_ON_PHASE
) {
326 // since the border can not be turned off,
327 // we blink the first bar even if the actual value is zero
328 if (blinking
&& state
< 1) {
331 Ht1621Data1
[4] |= 0x40; // Battery border // TODO this is not working for me, the border is ALWAYS on
333 Ht1621Data1
[7] |= 0x80;
335 Ht1621Data1
[9] |= 0x80;
337 Ht1621Data1
[5] |= 0x80;
339 Ht1621Data1
[10] |= 0x80;
341 Ht1621Data1
[4] |= 0x80;
345 void setTopBatteryValue(uint32_t volts
)
355 segs
= r
? RssiLCDsegs
[1] : 0;
356 Ht1621Data2
[3] |= ((segs
& 7) << 1);
357 Ht1621Data2
[4] |= segs
& 0xF0;
358 segs
= (r
|| qr
.quot
) ? RssiLCDsegs
[qr
.quot
] : 0;
359 Ht1621Data2
[4] |= (segs
& 0x0E);
360 Ht1621Data2
[5] |= segs
& 0xF0;
361 segs
= RssiLCDsegs
[qr
.rem
];
362 Ht1621Data2
[5] |= (segs
& 0x0E) | 1; // Decimal point
363 Ht1621Data2
[6] |= segs
& 0xF0;
364 Ht1621Data1
[4] |= 0x20; // "V"
367 void setTopSecondTimer(uint32_t value
)
374 uint32_t secs
= qr
.rem
;
375 qr
= div(qr
.quot
, 60);
376 uint32_t mins
= qr
.rem
;
377 uint32_t hours
= min(qr
.quot
, 99);
380 segs
= OpTimeLCDsegs
[qr
.rem
];
381 Ht1621Data1
[4] |= (segs
& 0x0F) | 0x70;
383 segs2
= OpTimeLCDsegs
[qr
.quot
];
384 Ht1621Data1
[5] |= segs
| (segs2
& 0x0F);
387 segs
= OpTimeLCDsegs
[qr
.rem
];
389 Ht1621Data1
[6] |= segs2
| (segs
& 0x0F) | 0x80; // ":"
391 segs2
= OpTimeLCDsegs
[qr
.quot
];
392 Ht1621Data1
[7] |= segs
| (segs2
& 0x0F);
395 segs
= OpTimeLCDsegs
[qr
.rem
];
397 Ht1621Data1
[8] |= segs2
| (segs
& 0x0F) | 0x80; // ":"
399 segs2
= OpTimeLCDsegs
[qr
.quot
];
400 Ht1621Data1
[9] |= segs
| (segs2
& 0x0F);
401 Ht1621Data1
[10] |= segs2
& 0xF0;
403 Ht1621Data1
[3] |= 0x10; // "Operation Time"
406 void toplcdRefreshStart()
408 memset(Ht1621Data1
, 0, sizeof(Ht1621Data1
));
409 memset(Ht1621Data2
, 0, sizeof(Ht1621Data2
));
412 void toplcdRefreshEnd()
414 ht1621WrAllData(0, Ht1621Data1
);
415 ht1621WrAllData(1, Ht1621Data2
);