1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-20 14:55:13 +03:00

Simu async lcd display

This commit is contained in:
bsongis 2011-11-28 21:32:04 +00:00
parent a82d2346a8
commit 6a579226cd
10 changed files with 102 additions and 78 deletions

View file

@ -17,6 +17,7 @@
*
*/
#define PROGRESS_VERTICAL_BAR
#include "gruvin9x.h"
#include "stdio.h"
@ -457,7 +458,11 @@ void RlcFile::writeRlc(uint8_t i_fileId, uint8_t typ, uint8_t*buf, uint16_t i_le
m_rlc_buf = buf;
m_rlc_len = i_len;
m_cur_rlc_len = 0;
m_ratio = (typ == FILE_TYP_MODEL ? 60 : 7);
#if defined (PROGRESS_CIRCLE)
m_ratio = (typ == FILE_TYP_MODEL ? 60 : 6);
#elif defined (PROGRESS_VERTICAL_BAR)
m_ratio = (typ == FILE_TYP_MODEL ? 100 : 10);
#endif
do {
nextRlcWriteStep();
@ -573,10 +578,9 @@ void RlcFile::flush()
s_sync_write = false;
}
#define PROGRESS_CIRCLE
void RlcFile::DisplayProgressBar(uint8_t x)
{
if (s_eeDirtyMsk || m_rlc_len || eeprom_buffer_size) {
if (s_eeDirtyMsk || isWriting() || eeprom_buffer_size) {
#if defined (PROGRESS_BAR)
uint8_t len = (s_eeDirtyMsk ? 123 : min((uint8_t)123, (uint8_t)((m_rlc_len) / 5 + eeprom_buffer_size)));
lcd_filled_rect(2, 1, 125, 5, WHITE);
@ -585,11 +589,17 @@ void RlcFile::DisplayProgressBar(uint8_t x)
lcd_filled_rect(x-1, 0, 7, 7, WHITE);
uint8_t len = s_eeDirtyMsk ? 1 : limit(1, 12 - (uint8_t)(m_rlc_len/m_ratio), 12);
lcd_hline(x+1, 1, min((uint8_t)3, len));
if (len >= 3) lcd_vline(x+4, 2, min(3, len-3));
if (len >= 6) lcd_hline(x+4, 1+4, -min(3, len-6));
if (len >= 9) lcd_vline(x, 5, -min(3, len-9));
if (len >= 3) {
lcd_vline(x+4, 2, min(3, len-3));
if (len >= 6) {
lcd_hline(x+4, 1+4, -min(3, len-6));
if (len >= 9) {
lcd_vline(x, 5, -min(3, len-9));
}
}
}
#elif defined (PROGRESS_VERTICAL_BAR)
uint8_t len = 6 - (s_eeDirtyMsk ? 5 : min((uint8_t)5, (uint8_t)((m_rlc_len / 100) + (eeprom_buffer_size / 10))));
uint8_t len = s_eeDirtyMsk ? 1 : limit((uint8_t)1, (uint8_t)(7 - (m_rlc_len/m_ratio)), (uint8_t)7);
lcd_filled_rect(x+1, 0, 5, FH, WHITE);
lcd_filled_rect(x+2, 7-len, 3, len);
#elif defined (PROGRESS_FIXED_CIRCLE)

View file

@ -504,7 +504,7 @@ void doSplash()
lcd_clear();
lcd_img(0, 0, s9xsplash,0,0);
refreshDiplay();
refreshDisplay();
lcdSetRefVolt(g_eeGeneral.contrast);
clearKeyEvents();
@ -554,7 +554,7 @@ void alertMessages( const prog_char * s, const prog_char * t )
lcd_puts_P(0,4*FH,s);
lcd_puts_P(0,5*FH,t);
lcd_puts_P(0,6*FH, PSTR("Press any key to skip") ) ;
refreshDiplay();
refreshDisplay();
lcdSetRefVolt(g_eeGeneral.contrast);
clearKeyEvents();
@ -638,7 +638,7 @@ void message(const prog_char * s)
lcd_clear();
lcd_putsAtt(64-5*FW,0*FH,PSTR("MESSAGE"),DBLSIZE);
lcd_puts_P(0,4*FW,s);
refreshDiplay();
refreshDisplay();
lcdSetRefVolt(g_eeGeneral.contrast);
}
@ -648,7 +648,7 @@ void alert(const prog_char * s, bool defaults)
lcd_putsAtt(64-5*FW,0*FH,PSTR("ALERT"),DBLSIZE);
lcd_puts_P(0,4*FH,s);
lcd_puts_P(64-6*FW,7*FH,PSTR("press any Key"));
refreshDiplay();
refreshDisplay();
lcdSetRefVolt(defaults ? 25 : g_eeGeneral.contrast);
beepErr();
clearKeyEvents();
@ -1708,7 +1708,7 @@ void perMain()
/////////////////
g_menuStack[g_menuStackPtr](evt);
refreshDiplay();
refreshDisplay();
#if defined (PCBV4)
// PPM signal on phono-jack. In or out? ...
@ -2125,7 +2125,7 @@ void moveTrimsToOffsets() // copy state of 3 primary to subtrim
s_noStickInputs = false;
for (uint8_t i=0; i<NUM_CHNOUT; i++)
g_model.limitData[i].offset = max(min(zero_chans512[i], (int16_t)1000), (int16_t)-1000); // make sure the offset doesn't go haywire
g_model.limitData[i].offset = limit((int16_t)-1000, zero_chans512[i], (int16_t)1000); // make sure the offset doesn't go haywire
// reset all trims, except throttle
for (uint8_t i=0; i<4; i++) {

View file

@ -508,9 +508,11 @@ extern uint16_t s_traceCnt;
uint16_t getTmr16KHz();
uint16_t stack_free();
void doSplash();
void checkLowEEPROM();
void checkTHR();
void checkSwitches();
void checkAlarm();
#define GETADC_SING = 0
#define GETADC_OSMP = 1
@ -547,11 +549,11 @@ extern uint8_t s_eeDirtyMsk;
/// liefert Betrag des Arguments
template<class t> inline t __attribute__ ((always_inline)) abs(t a){ return a>0?a:-a; }
/// liefert das Minimum der Argumente
template<class t> inline t min(t a, t b){ return a<b?a:b; }
template<class t> inline t __attribute__ ((always_inline)) min(t a, t b){ return a<b?a:b; }
/// liefert das Maximum der Argumente
template<class t> inline t max(t a, t b){ return a>b?a:b; }
template<class t> inline int8_t sgn(t a){ return a>0 ? 1 : (a < 0 ? -1 : 0); }
template<class t> inline t limit(t mi, t x, t ma){ return min(max(mi,x),ma); }
template<class t> inline t __attribute__ ((always_inline)) max(t a, t b){ return a>b?a:b; }
template<class t> inline int8_t __attribute__ ((always_inline)) sgn(t a){ return a>0 ? 1 : (a < 0 ? -1 : 0); }
template<class t> inline t __attribute__ ((always_inline)) limit(t mi, t x, t ma){ return min(max(mi,x),ma); }
/// Markiert einen EEPROM-Bereich als dirty. der Bereich wird dann in
/// eeCheck ins EEPROM zurueckgeschrieben.

View file

@ -29,6 +29,11 @@ uint8_t displayBuf[DISPLAY_W*DISPLAY_H/8];
#include "font_dblsize.lbm"
#define font_10x16_x20_x7f (font_dblsize+3)
#ifdef SIMU
bool lcd_refresh = true;
uint8_t lcd_buf[DISPLAY_W*DISPLAY_H/8];
#endif
void lcd_clear()
{
memset(displayBuf, 0, sizeof(displayBuf));
@ -557,8 +562,12 @@ void lcdSetRefVolt(uint8_t val)
lcdSendCtl(val);
}
void refreshDiplay()
void refreshDisplay()
{
#ifdef SIMU
memcpy(lcd_buf, displayBuf, sizeof(displayBuf));
lcd_refresh = true;
#else
uint8_t *p=displayBuf;
for(uint8_t y=0; y < 8; y++) {
lcdSendCtl(0x04);
@ -578,4 +587,5 @@ void refreshDiplay()
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
#endif
}

View file

@ -129,11 +129,15 @@ extern void lcdSetRefVolt(unsigned char val);
extern void lcd_init();
extern void lcd_clear();
extern void refreshDiplay();
extern void refreshDisplay();
#define BLINK_ON_PHASE (g_blinkTmr10ms & (1<<6))
#define BLINK_SYNC g_blinkTmr10ms = (3<<5)
#ifdef SIMU
extern bool lcd_refresh;
extern uint8_t lcd_buf[DISPLAY_W*DISPLAY_H/8];
#endif
#endif
/*eof*/

View file

@ -110,7 +110,7 @@ void displayPopup(const prog_char * pstr)
s_warning = pstr;
displayBox();
s_warning = 0;
refreshDiplay();
refreshDisplay();
}
void displayWarning(uint8_t event)
@ -240,6 +240,7 @@ void menuProcModelSelect(uint8_t event)
s_copyMode = 0; // TODO only this one?
s_copySrcRow = -1;
s_copyTgtOfs = 0;
return;
}
else if (_event == EVT_KEY_LONG(KEY_MENU)) {
displayPopup(PSTR("Loading model..."));
@ -249,6 +250,7 @@ void menuProcModelSelect(uint8_t event)
STORE_GENERALVARS;
eeLoadModel(sub);
}
s_copyMode = 0;
killEvents(event);
return;
}
@ -497,9 +499,8 @@ void menuProcModel(uint8_t event)
}
else if (sub==subN) {
m_posHorz = 0;
CHECK_INCDEC_MODELVAR(event,g_model.protocol,0,PROT_MAX);
}
if(sub==subN && (s_editMode || p1valdiff)) {
if (sub==subN && (s_editMode || p1valdiff || !g_model.protocol)) {
switch (m_posHorz) {
case 0:
CHECK_INCDEC_MODELVAR(event,g_model.protocol,0,PROT_MAX);

View file

@ -21,8 +21,6 @@
#include "gruvin9x.h"
#ifndef SIMU
#ifdef CTP1009
uint16_t pulses2MHz[50] = {0};
#else
@ -37,6 +35,8 @@ uint16_t *pulses2MHzWPtr = pulses2MHz;
#define CTRL_REP_1CMD -3
#define CTRL_REP_2CMD -6
#ifndef SIMU
ISR(TIMER1_COMPA_vect) //2MHz pulse generation
{
static uint8_t pulsePol; // TODO strange, it's always 0 at first, shouldn't it be initialized properly in setupPulses?
@ -44,8 +44,6 @@ ISR(TIMER1_COMPA_vect) //2MHz pulse generation
// Latency -- how far further on from interrupt trigger has the timer counted?
// (or -- how long did it take to get to this function)
uint8_t dt = TCNT1L;
if (dt > g_tmr1Latency_max) g_tmr1Latency_max = dt;
if (dt < g_tmr1Latency_min) g_tmr1Latency_min = dt;
// vinceofdrink@gmail harwared ppm
// Orginal bitbang for PPM
@ -83,6 +81,9 @@ ISR(TIMER1_COMPA_vect) //2MHz pulse generation
// much change in the code not optimum but will not alter ppm precision
#endif
if (dt > g_tmr1Latency_max) g_tmr1Latency_max = dt;
if (dt < g_tmr1Latency_min) g_tmr1Latency_min = dt;
++pulses2MHzRPtr;
if (pulses2MHzRPtr == pulses2MHzWPtr) {
@ -91,7 +92,6 @@ ISR(TIMER1_COMPA_vect) //2MHz pulse generation
// channel = 0 ;
// PulseTotal = 0 ;
// cli(); // TODO I remove this cli, we are in a blocking interrupt
#if defined (PCBV3)
TIMSK1 &= ~(1<<OCIE1A); //stop reentrance
#else
@ -114,11 +114,13 @@ ISR(TIMER1_COMPA_vect) //2MHz pulse generation
#else
TIMSK |= (1<<OCIE1A);
#endif
// sei(); TODO I remove this sei
sei();
}
heartbeat |= HEART_TIMER2Mhz;
}
#endif
//inline int16_t reduceRange(int16_t x) // for in case we want to have room for subtrims
//{
// return x-(x/4); //512+128 =? 640, 640 - 640/4 == 640 * 3/4 => 480 (just below 500msec - it can still reach 500 with offset)
@ -146,7 +148,7 @@ inline void __attribute__ ((always_inline)) setupPulsesPPM() // changed 10/05/20
rest += (int16_t(g_model.ppmFrameLength))*1000;
if(p>9) rest=p*(1720u*2 + q) + 4000u*2; //for more than 9 channels, frame must be longer
for (uint8_t i=0; i<p; i++) {
int16_t v = max(min(g_chans512[i], PPM_range), -PPM_range) + PPM_CENTER;
int16_t v = limit(-PPM_range, g_chans512[i], PPM_range) + PPM_CENTER;
rest -= (v+q);
*ptr++ = q;
*ptr++ = v - q + 600; /* as Pat MacKenzie suggests */
@ -441,5 +443,4 @@ void setupPulses()
#endif
}
}
#endif

View file

@ -35,7 +35,7 @@ extern uint16_t eeprom_pointer;
extern const char* eeprom_buffer_data;
uint8_t eeprom[EESIZE];
sem_t eeprom_write_sem;
pthread_t write_thread_pid = 0;
pthread_t eeprom_thread_pid = 0;
void *eeprom_write_function(void *)
{
@ -75,7 +75,7 @@ void *eeprom_write_function(void *)
void InitEepromThread()
{
sem_init(&eeprom_write_sem, 0, 0);
assert(!pthread_create(&write_thread_pid, NULL, &eeprom_write_function, NULL));
assert(!pthread_create(&eeprom_thread_pid, NULL, &eeprom_write_function, NULL));
}
void eeprom_read_block (void *pointer_ram,

View file

@ -19,6 +19,9 @@
*
*/
#ifndef simpgmspace_h
#define simpgmspace_h
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
@ -90,3 +93,5 @@ void eeprom_read_block (void *pointer_ram,
#undef offsetof
#define offsetof(st, m) ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))
#define wdt_reset()
#endif

View file

@ -24,7 +24,6 @@
#include "FXPNGImage.h"
#include <unistd.h>
#include "simpgmspace.h"
#include "lcd.h"
#include "fxkeys.h"
#include "gruvin9x.h"
#include "menus.h"
@ -46,7 +45,6 @@ public:
Gruvin9xSim(FXApp* a);
long onKeypress(FXObject*,FXSelector,void*);
long onArrowPress(FXObject*,FXSelector,void*);
long onChore(FXObject*,FXSelector,void*);
long onTimeout(FXObject*,FXSelector,void*);
void makeSnapshot(const FXDrawable* drawable);
void doEvents();
@ -71,7 +69,6 @@ public:
FXDEFMAP(Gruvin9xSim) Gruvin9xSimMap[]={
//________Message_Type_________ID_____________________Message_Handler_______
FXMAPFUNC(SEL_CHORE, 1, Gruvin9xSim::onChore),
FXMAPFUNC(SEL_TIMEOUT, 2, Gruvin9xSim::onTimeout),
FXMAPFUNC(SEL_COMMAND, 1000, Gruvin9xSim::onArrowPress),
FXMAPFUNC(SEL_KEYPRESS, 0, Gruvin9xSim::onKeypress),
@ -237,35 +234,38 @@ long Gruvin9xSim::onTimeout(FXObject*,FXSelector,void*)
}
per10ms();
getApp()->addChore(this,1);
refreshDiplay();
getApp()->addTimeout(this,2,10);
return 0;
}
void Gruvin9xSim::refreshDiplay()
{
if(portb & 1<<OUT_B_LIGHT) bmf->setOffColor(FXRGB(150,200,152));
else bmf->setOffColor(FXRGB(200,200,200));
if (lcd_refresh) {
lcd_refresh = false;
if(portb & 1<<OUT_B_LIGHT) bmf->setOffColor(FXRGB(150,200,152));
else bmf->setOffColor(FXRGB(200,200,200));
for(int x=0;x<W;x++){
for(int y=0;y<H;y++)
{
int o2 = x/4 + y*W*2*2/8;
if( displayBuf[x+(y/8)*W] & (1<<(y%8))) {
buf2[o2] |= 3<<(x%4*2);
buf2[o2+W2/8] |= 3<<(x%4*2);
}
else {
buf2[o2] &= ~(3<<(x%4*2));
buf2[o2+W2/8] &= ~(3<<(x%4*2));
//buf2[x2/8+y2*W2/8] &= ~(3<<(x%8));
for(int x=0;x<W;x++){
for(int y=0;y<H;y++)
{
int o2 = x/4 + y*W*2*2/8;
if( lcd_buf[x+(y/8)*W] & (1<<(y%8))) {
buf2[o2] |= 3<<(x%4*2);
buf2[o2+W2/8] |= 3<<(x%4*2);
}
else {
buf2[o2] &= ~(3<<(x%4*2));
buf2[o2+W2/8] &= ~(3<<(x%4*2));
//buf2[x2/8+y2*W2/8] &= ~(3<<(x%8));
}
}
}
bmp->setData (buf2,0);
bmp->render();
bmf->setBitmap( bmp );
}
bmp->setData (buf2,0);
bmp->render();
bmf->setBitmap( bmp );
if(hasFocus()) {
static FXuint keys1[]={
@ -351,34 +351,22 @@ void Gruvin9xSim::refreshDiplay()
}
}
int state = 0;
void *init_function(void *) {
void *main_thread(void *)
{
g_menuStack[0] = menuMainView;
g_menuStack[1] = menuProcModelSelect;
eeReadAll(); //load general setup and selected model
checkLowEEPROM(); //enough eeprom free?
doSplash();
checkLowEEPROM();
checkTHR();
checkSwitches(); //must be last
state = 2;
return 0;
}
checkSwitches();
checkAlarm();
long Gruvin9xSim::onChore(FXObject*,FXSelector,void*)
{
pthread_t pid;
refreshDiplay();
switch (state) {
case 0:
state = 1;
pthread_create(&pid, NULL, &init_function, NULL);
break;
case 2:
perMain();
break;
while(1) {
perMain();
usleep(1000);
}
return 0;
}
@ -397,8 +385,6 @@ int main(int argc,char **argv)
}
printf("eeprom = %s\n", eepromFile);
InitEepromThread();
// Each FOX GUI program needs one, and only one, application object.
// The application objects coordinates some common stuff shared between
// all the widgets; for example, it dispatches events, keeps track of
@ -431,6 +417,11 @@ int main(int argc,char **argv)
th9xSim->show(); // Otherwise the main window gets centred across my two monitors, split down the middle.
#endif
InitEepromThread();
pthread_t pid;
pthread_create(&pid, NULL, &main_thread, NULL);
return application.run();
}