Issues with current model during copy / move operations in MODELSEL menu.

This commit is contained in:
bsongis
2011-11-25 11:04:38 +00:00
parent 5d9a2a483b
commit 9761da9de3
12 changed files with 576 additions and 556 deletions
+1 -3
View File
@@ -80,7 +80,7 @@ DISPLAY_USER_DATA = NO
PXX = NO
# DSM2 (Spektrum) protocol
DSM2 = YES
DSM2 = NO
# Silver protocol
SILVER = NO
@@ -178,8 +178,6 @@ CPPDEFS = -DF_CPU=$(F_CPU)UL
# NOTE: PCB version now overrides all the earlier individual settings
# These individual settings work only for PCB=STD
CPPDEFS += -DEEPROM_ASYNC_WRITE
ifeq ($(PCB), STD)
# STD PCB, so ...
+4 -46
View File
@@ -23,8 +23,6 @@
#ifndef SIMU
#ifdef EEPROM_ASYNC_WRITE
uint16_t eeprom_pointer;
const char* eeprom_buffer_data;
volatile int8_t eeprom_buffer_size = 0;
@@ -77,50 +75,6 @@ void eeWriteBlockCmp(const void *i_pointer_ram, void *i_pointer_eeprom, size_t s
}
}
#else
///opt/cross/avr/include/avr/eeprom.h
static inline void __attribute__ ((always_inline))
eeprom_write_byte_cmp (uint8_t dat, uint16_t pointer_eeprom)
{
//see /home/thus/work/avr/avrsdk4/avr-libc-1.4.4/libc/misc/eeprom.S:98 143
#if defined (PCBV3)
while(EECR & (1<<EEPE))
#else
while(EECR & (1<<EEWE))
#endif
;
EEAR = pointer_eeprom;
EECR |= 1<<EERE;
if(dat == EEDR) return;
EEDR = dat;
uint8_t flags=SREG;
cli();
#if defined (PCBV3)
EECR |= 1<<EEMPE;
EECR |= 1<<EEPE;
#else
EECR |= 1<<EEMWE;
EECR |= 1<<EEWE;
#endif
SREG = flags;
sei();
}
void eeWriteBlockCmp(const void *i_pointer_ram, void *i_pointer_eeprom, size_t size)
{
const char* pointer_ram = (const char*)i_pointer_ram;
uint16_t pointer_eeprom = (uint16_t)i_pointer_eeprom;
while(size){
eeprom_write_byte_cmp(*pointer_ram++,pointer_eeprom++);
size--;
}
}
#endif
#endif
@@ -255,6 +209,10 @@ bool keyState(EnumKeys enuk)
case SW_Trainer: return PINB & (1<<INP_B_Trainer);
case SW_RE1: return (~PIND & 0b00100000);
case SW_RE2: return (~PIND & 0b00010000);
default:;
}
#else
+121 -231
View File
@@ -24,9 +24,7 @@
#include "string.h"
uint8_t s_write_err = 0; // error reasons
#ifdef EEPROM_ASYNC_WRITE
uint8_t s_sync_write = false;
#endif
#define RESV 64 //reserv for eeprom header with directory (eeFs)
#define FIRSTBLK (RESV/BS)
@@ -48,32 +46,48 @@ struct EeFs{
}__attribute__((packed)) eeFs;
static uint8_t EeFsRead(uint8_t blk,uint8_t ofs){
static uint8_t EeFsRead(uint8_t blk,uint8_t ofs)
{
uint8_t ret;
eeprom_read_block(&ret,(const void*)(blk*BS+ofs),1);
return ret;
}
static void EeFsWrite(uint8_t blk,uint8_t ofs,uint8_t val){
static void EeFsWrite(uint8_t blk, uint8_t ofs, uint8_t val)
{
eeWriteBlockCmp(&val, (void*)(blk*BS+ofs), 1);
}
static uint8_t EeFsGetLink(uint8_t blk){
static uint8_t EeFsGetLink(uint8_t blk)
{
return EeFsRead( blk,0);
}
static void EeFsSetLink(uint8_t blk,uint8_t val){
static void EeFsSetLink(uint8_t blk,uint8_t val)
{
EeFsWrite( blk,0,val);
}
static uint8_t EeFsGetDat(uint8_t blk,uint8_t ofs){
static uint8_t EeFsGetDat(uint8_t blk,uint8_t ofs)
{
return EeFsRead( blk,ofs+1);
}
static void EeFsSetDat(uint8_t blk,uint8_t ofs,uint8_t*buf,uint8_t len){
//EeFsWrite( blk,ofs+1,val);
static void EeFsSetDat(uint8_t blk,uint8_t ofs,uint8_t*buf,uint8_t len)
{
eeWriteBlockCmp(buf, (void*)(blk*BS+ofs+1), len);
}
static void EeFsFlushFreelist()
{
eeWriteBlockCmp(&eeFs.freeList,&((EeFs*)0)->freeList ,sizeof(eeFs.freeList));
}
static void EeFsFlushDirEnt(uint8_t i_fileId)
{
eeWriteBlockCmp(&eeFs.files[i_fileId], &((EeFs*)0)->files[i_fileId], sizeof(DirEnt));
}
static void EeFsFlush()
{
eeWriteBlockCmp(&eeFs, 0,sizeof(eeFs));
@@ -90,7 +104,6 @@ uint16_t EeFsGetFree()
return ret;
}
// #ifndef EEPROM_ASYNC_WRITE TODO because duplicate code
static void EeFsFree(uint8_t blk){///free one or more blocks
uint8_t i = blk;
while( EeFsGetLink(i)) i = EeFsGetLink(i);
@@ -98,25 +111,10 @@ static void EeFsFree(uint8_t blk){///free one or more blocks
eeFs.freeList = blk; //chain in front
EeFsFlushFreelist();
}
// #endif
#ifndef EEPROM_ASYNC_WRITE
static uint8_t EeFsAlloc(){ ///alloc one block from freelist
uint8_t ret=eeFs.freeList;
if(ret){
eeFs.freeList = EeFsGetLink(ret);
EeFsFlushFreelist();
EeFsSetLink(ret,0);
}
return ret;
}
#endif
int8_t EeFsck()
{
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = true;
#endif
uint8_t *bufp;
static uint8_t buffer[BLOCKS];
@@ -129,45 +127,45 @@ int8_t EeFsck()
uint8_t *startP = i==MAXFILES ? &eeFs.freeList : &eeFs.files[i].startBlk;
uint8_t lastBlk = 0;
blk = *startP;
while(blk){
if( ( blk < FIRSTBLK ) //goto err_1; //bad blk index
|| (blk >= BLOCKS ) //goto err_2; //bad blk index
|| (bufp[blk] ))//goto err_3; //blk double usage
while (blk) {
if (blk < FIRSTBLK || // bad blk index
blk >= BLOCKS || // bad blk index
bufp[blk]) // blk double usage
{
if(lastBlk){
EeFsSetLink(lastBlk,0);
}else{
*startP = 0; //interrupt chain at startpos
if (lastBlk) {
EeFsSetLink(lastBlk, 0);
}
else {
*startP = 0; // interrupt chain at startpos
EeFsFlush();
}
blk=0; //abort
}else{
blk = 0; // abort
}
else {
bufp[blk] = i+1;
lastBlk = blk;
blk = EeFsGetLink(blk);
}
}
}
for(blk = FIRSTBLK; blk < BLOCKS; blk++){
if(bufp[blk]==0) { //goto err_4; //unused block
EeFsSetLink(blk,eeFs.freeList);
eeFs.freeList = blk; //chain in front
for (blk=FIRSTBLK; blk<BLOCKS; blk++) {
if (!bufp[blk]) { // unused block
EeFsSetLink(blk, eeFs.freeList);
eeFs.freeList = blk; // chain in front
EeFsFlushFreelist();
}
}
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = false;
#endif
return ret;
}
void EeFsFormat()
{
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = true;
#endif
if(sizeof(eeFs) != RESV){
if (sizeof(eeFs) != RESV){
extern void eeprom_RESV_mismatch();
eeprom_RESV_mismatch();
}
@@ -180,14 +178,14 @@ void EeFsFormat()
EeFsSetLink(BLOCKS-1, 0);
eeFs.freeList = FIRSTBLK;
EeFsFlush();
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = false;
#endif
}
bool EeFsOpen()
{
eeprom_read_block(&eeFs,0,sizeof(eeFs));
#ifdef SIMU
if(eeFs.version != EEFS_VERS) printf("bad eeFs.version\n");
if(eeFs.mySize != sizeof(eeFs)) printf("bad eeFs.mySize\n");
@@ -202,39 +200,41 @@ bool EFile::exists(uint8_t i_fileId)
}
/*
* swap two files in eeprom
* called in sync AND async mode as it is a single write operation
* Swap two files in eeprom
*/
void EFile::swap(uint8_t i_fileId1, uint8_t i_fileId2)
{
DirEnt tmp = eeFs.files[i_fileId1];
eeFs.files[i_fileId1] = eeFs.files[i_fileId2];
eeFs.files[i_fileId2] = tmp;
EeFsFlush();
s_sync_write = true;
EeFsFlushDirEnt(i_fileId1);
EeFsFlushDirEnt(i_fileId2);
s_sync_write = false;
}
void EFile::rm(uint8_t i_fileId)
{
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = true;
#endif
uint8_t i = eeFs.files[i_fileId].startBlk;
memset(&eeFs.files[i_fileId], 0, sizeof(eeFs.files[i_fileId]));
EeFsFlush(); //chained out
if(i) EeFsFree( i ); //chain in
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = true;
EeFsFlushDirEnt(i_fileId);
if (i) EeFsFree(i); //chain in
s_sync_write = false;
#endif
}
uint16_t EFile::size(){
uint16_t EFile::size()
{
return eeFs.files[m_fileId].size;
}
// G: Open file ID for reading. Return the file's type
void EFile::openRd(uint8_t i_fileId){
/*
* Open file i_fileId for reading.
* Return the file's type
*/
void EFile::openRd(uint8_t i_fileId)
{
m_fileId = i_fileId;
m_pos = 0;
m_currBlk = eeFs.files[m_fileId].startBlk;
@@ -249,7 +249,8 @@ void RlcFile::openRlc(uint8_t i_fileId)
m_bRlc = 0;
}
uint8_t EFile::read(uint8_t*buf,uint16_t i_len){
uint8_t EFile::read(uint8_t*buf,uint16_t i_len)
{
uint16_t len = eeFs.files[m_fileId].size - m_pos;
if(len < i_len) i_len = len;
len = i_len;
@@ -267,7 +268,9 @@ uint8_t EFile::read(uint8_t*buf,uint16_t i_len){
return i_len - len;
}
// G: Read runlength (RLE) compressed bytes into buf.
/*
* Read runlength (RLE) compressed bytes into buf.
*/
#ifdef TRANSLATIONS
uint16_t RlcFile::readRlc12(uint8_t*buf,uint16_t i_len, bool rlc2)
#else
@@ -316,8 +319,6 @@ uint16_t RlcFile::readRlc(uint8_t*buf,uint16_t i_len)
return i;
}
#ifdef EEPROM_ASYNC_WRITE
void RlcFile::write1(uint8_t b)
{
m_write1_byte = b;
@@ -336,18 +337,18 @@ void RlcFile::write(uint8_t *buf, uint8_t i_len)
void RlcFile::nextWriteStep()
{
if(!m_currBlk && m_pos==0)
{
if(!m_currBlk && m_pos==0) {
eeFs.files[FILE_TMP].startBlk = m_currBlk = eeFs.freeList;
if (m_currBlk) {
eeFs.freeList = EeFsGetLink(m_currBlk);
m_write_step = WRITE_START_STEP + WRITE_FIRST_LINK;
m_write_step |= WRITE_FIRST_LINK;
EeFsFlushFreelist();
return;
}
}
if (m_write_step == WRITE_START_STEP + WRITE_FIRST_LINK) {
m_write_step = WRITE_START_STEP;
if ((m_write_step & 0x0f) == WRITE_FIRST_LINK) {
m_write_step -= WRITE_FIRST_LINK;
EeFsSetLink(m_currBlk, 0);
return;
}
@@ -405,59 +406,6 @@ void RlcFile::nextWriteStep()
nextRlcWriteStep();
}
#else
uint8_t RlcFile::write1(uint8_t b)
{
return write(&b,1);
}
uint8_t RlcFile::write(uint8_t*buf, uint8_t i_len)
{
uint8_t len=i_len;
if(!m_currBlk && m_pos==0)
{
eeFs.files[m_fileId].startBlk = m_currBlk = EeFsAlloc();
}
while(len)
{
#ifndef SIMU
if( (int16_t)(m_stopTime10ms - get_tmr10ms()) < 0)
{
s_write_err = ERR_TMO;
break;
}
#endif
if(!m_currBlk) {
s_write_err = ERR_FULL;
break;
}
if(m_ofs>=(BS-1)){
m_ofs=0;
if( ! EeFsGetLink(m_currBlk) ){
EeFsSetLink(m_currBlk, EeFsAlloc());
}
m_currBlk = EeFsGetLink(m_currBlk);
}
if(!m_currBlk) {
s_write_err = ERR_FULL;
break;
}
uint8_t l = BS-1-m_ofs; if(l>len) l=len;
EeFsSetDat(m_currBlk, m_ofs, buf, l);
buf +=l;
m_ofs +=l;
len -=l;
}
m_pos += i_len - len;
return i_len - len;
}
#endif
#ifdef EEPROM_ASYNC_WRITE
void RlcFile::create(uint8_t i_fileId, uint8_t typ, uint8_t sync_write)
{
// all write operations will be executed on FILE_TMP
@@ -468,6 +416,41 @@ void RlcFile::create(uint8_t i_fileId, uint8_t typ, uint8_t sync_write)
s_sync_write = sync_write;
}
/*
* Copy file src to dst
*/
bool RlcFile::copy(uint8_t i_fileDst, uint8_t i_fileSrc)
{
EFile theFile2;
theFile2.openRd(i_fileSrc);
create(i_fileDst, FILE_TYP_MODEL/*optimization, only model files are copied. should be eeFs.files[i_fileSrc].typ*/, true);
uint8_t buf[15];
uint8_t len;
while ((len=theFile2.read(buf, 15)))
{
write(buf, len);
if (errno() != 0) {
s_sync_write = false;
return false;
}
}
uint8_t fri=0;
if (m_currBlk && (fri=EeFsGetLink(m_currBlk)))
EeFsSetLink(m_currBlk, 0);
eeFs.files[FILE_TMP].size = m_pos;
EFile::swap(m_fileId, FILE_TMP);
if (fri) EeFsFree(fri); //chain in
assert(!m_write_step);
s_sync_write = false;
return true;
}
void RlcFile::writeRlc(uint8_t i_fileId, uint8_t typ, uint8_t*buf, uint16_t i_len, uint8_t sync_write)
{
create(i_fileId, typ, sync_write);
@@ -541,7 +524,7 @@ void RlcFile::nextRlcWriteStep()
case WRITE_START_STEP:
{
uint8_t fri=0;
eeFs.files[FILE_TMP].size = m_pos;
if (m_currBlk && ( fri = EeFsGetLink(m_currBlk))) {
uint8_t prev_freeList = eeFs.freeList;
eeFs.freeList = fri;
@@ -552,9 +535,19 @@ void RlcFile::nextRlcWriteStep()
}
}
case WRITE_FLUSH_STEP: // TODO could be avoided
m_write_step = WRITE_SWAP_STEP;
EeFsFlush(); //chained out
case WRITE_FINAL_DIRENT_STEP:
m_currBlk = eeFs.files[FILE_TMP].startBlk;
eeFs.files[FILE_TMP].startBlk = eeFs.files[m_fileId].startBlk;
eeFs.files[m_fileId].startBlk = m_currBlk;
eeFs.files[m_fileId].size = m_pos;
eeFs.files[m_fileId].typ = eeFs.files[FILE_TMP].typ;
m_write_step = WRITE_TMP_DIRENT_STEP;
EeFsFlushDirEnt(m_fileId);
return;
case WRITE_TMP_DIRENT_STEP:
m_write_step = 0;
EeFsFlushDirEnt(FILE_TMP);
return;
case WRITE_FREE_UNUSED_BLOCKS_STEP1:
@@ -563,13 +556,9 @@ void RlcFile::nextRlcWriteStep()
return;
case WRITE_FREE_UNUSED_BLOCKS_STEP2:
m_write_step = WRITE_FLUSH_STEP;
m_write_step = WRITE_FINAL_DIRENT_STEP;
EeFsFlushFreelist();
return;
case WRITE_SWAP_STEP:
m_write_step = 0;
EFile::swap(m_fileId, FILE_TMP);
}
}
@@ -585,103 +574,4 @@ void RlcFile::flush()
s_sync_write = false;
}
#else
void RlcFile::create(uint8_t i_fileId, uint8_t typ, uint16_t maxTme10ms)
{
openRlc(i_fileId); //internal use
eeFs.files[i_fileId].typ = typ;
eeFs.files[i_fileId].size = 0;
m_stopTime10ms = get_tmr10ms() + maxTme10ms;
}
// G: Write runlength (RLE) compressed bytes
uint16_t RlcFile::writeRlc(uint8_t i_fileId, uint8_t typ,uint8_t*buf,uint16_t i_len, uint8_t maxTme10ms){
create(i_fileId,typ,maxTme10ms);
bool run0 = buf[0] == 0;
uint8_t cnt = 1;
uint8_t cnt0 = 0;
uint16_t i = 0;
if(i_len==0) goto close;
//RLE compression:
//rb = read byte
//if (rb | 0x80) write rb & 0x7F zeros
//else write rb bytes
for( i=1; 1 ; i++) // !! laeuft ein byte zu weit !!
{
bool cur0 = buf[i] == 0;
if(cur0 != run0 || cnt==0x3f || (cnt0 && cnt==0xf)|| i==i_len){
if(run0){
assert(cnt0==0);
if(cnt<8 && i!=i_len)
cnt0 = cnt; //aufbew fuer spaeter
else {
if( write1(cnt|0x40)!=1) goto error;//-cnt&0x3f
}
}else{
if(cnt0){
if( write1(0x80 | (cnt0<<4) | cnt)!=1) goto error;//-cnt0xx-cnt
cnt0 = 0;
}else{
if( write1(cnt) !=1) goto error;//-cnt
}
uint8_t ret=write(&buf[i-cnt],cnt);
if( ret !=cnt) { cnt-=ret; goto error;}//-cnt
}
cnt=0;
if(i==i_len) break;
run0 = cur0;
}
cnt++;
}
if(0){
error:
i-=cnt+cnt0;
#ifdef SIMU
switch(s_write_err){
default:
case ERR_NONE:
assert(!"missing errno");
break;
case ERR_FULL:
printf("ERROR filesystem overflow! written: %d missing: %d\n",i,i_len-i);
break;
case ERR_TMO:
printf("ERROR filesystem write timeout %d 0ms\n",(int16_t)(m_stopTime10ms - g_tmr10ms));
break;
}
#endif
}
close:
close();
return i;
}
#endif
// G: Close file and truncate at this blk. Add any remaining blocks to freeList chain
void RlcFile::close()
{
uint8_t fri=0;
if(m_currBlk && ( fri = EeFsGetLink(m_currBlk))) EeFsSetLink(m_currBlk, 0);
#ifdef EEPROM_ASYNC_WRITE
eeFs.files[FILE_TMP].size = m_pos;
EFile::swap(m_fileId, FILE_TMP);
#else
eeFs.files[m_fileId].size = m_pos;
EeFsFlush(); //chained out
#endif
if(fri) EeFsFree( fri ); //chain in
#ifdef EEPROM_ASYNC_WRITE
m_write_step = 0;
s_sync_write = false;
#endif
}
+12 -36
View File
@@ -29,12 +29,15 @@
// bs=32 64 blocks verlust link: 64 16files:16*16 256 sum 320
//
#if defined(PCBV3)
#define EESIZE 4096
#define BS 32
// 4096 - 16 bytes to give 255 blocks, since we can't address 256 block in an 8-bit register
#define EESIZE 4080
#else
#define EESIZE 2048
#define BS 16
#endif
#define BS 16
#define FILE_TYP_GENERAL 1
#define FILE_TYP_MODEL 2
/// fileId of general file
#define FILE_GENERAL 0
@@ -47,9 +50,7 @@ int8_t EeFsck();
void EeFsFormat();
uint16_t EeFsGetFree();
#ifdef EEPROM_ASYNC_WRITE
extern volatile int8_t eeprom_buffer_size;
#endif
class EFile
{
@@ -82,9 +83,6 @@ class EFile
#define ERR_NONE 0
#define ERR_FULL 1
#ifndef EEPROM_ASYNC_WRITE
#define ERR_TMO 2
#endif
extern uint8_t s_write_err; // error reasons
extern uint8_t s_sync_write;
@@ -96,7 +94,6 @@ class RlcFile: public EFile
uint8_t m_bRlc; // control byte for run length decoder
uint8_t m_zeroes;
#ifdef EEPROM_ASYNC_WRITE
uint8_t m_flags;
#define WRITE_FIRST_LINK 0x01
#define WRITE_NEXT_LINK_1 0x02
@@ -104,8 +101,8 @@ class RlcFile: public EFile
#define WRITE_START_STEP 0x10
#define WRITE_FREE_UNUSED_BLOCKS_STEP1 0x20
#define WRITE_FREE_UNUSED_BLOCKS_STEP2 0x30
#define WRITE_FLUSH_STEP 0x40
#define WRITE_SWAP_STEP 0x50
#define WRITE_FINAL_DIRENT_STEP 0x40
#define WRITE_TMP_DIRENT_STEP 0x50
uint8_t m_write_step;
uint16_t m_rlc_len;
@@ -114,17 +111,16 @@ class RlcFile: public EFile
uint8_t m_write1_byte;
uint8_t m_write_len;
uint8_t * m_write_buf;
#else
uint16_t m_stopTime10ms; // maximum point of time for writing
#endif
public:
void openRlc(uint8_t i_fileId);
#ifdef EEPROM_ASYNC_WRITE
void create(uint8_t i_fileId, uint8_t typ, uint8_t sync_write);
///copy contents of i_fileSrc to i_fileDst
bool copy(uint8_t i_fileDst, uint8_t i_fileSrc);
inline bool isWriting() { return m_write_step != 0; }
void write(uint8_t*buf, uint8_t i_len);
void write1(uint8_t b);
@@ -132,26 +128,6 @@ public:
void nextRlcWriteStep();
void writeRlc(uint8_t i_fileId, uint8_t typ, uint8_t *buf, uint16_t i_len, uint8_t sync_write);
void flush();
#else
/// create a new file with given fileId,
/// !!! if this file already exists, then all blocks are reused
/// and all contents will be overwritten.
/// after writing close has to be called
void create(uint8_t i_fileId, uint8_t typ, uint16_t maxTme10ms);
uint8_t write(uint8_t*buf, uint8_t i_len);
uint8_t write1(uint8_t b);
///open file, write to file and close it.
///If file existed before, then contents is overwritten.
///If file was larger before, then unused blocks are freed
uint16_t writeRlc(uint8_t i_fileId, uint8_t typ,uint8_t*buf,uint16_t i_len, uint8_t maxTme10ms);
#endif
/*
* close file and truncate the blockchain if to long.
*/
void close();
///read from opened file and decode rlc-coded data
#ifdef TRANSLATIONS
+112 -2
View File
@@ -20,6 +20,8 @@
#include "gruvin9x.h"
#include "frsky.h"
#include "ff.h" // TODO
// #include <stdlib.h> // TODO
// Enumerate FrSky packet codes
#define LINKPKT 0xfe
@@ -76,6 +78,23 @@ void frskyPushValue(uint8_t *&ptr, uint8_t value)
}
}
#ifdef DISPLAY_USER_DATA
/*
Copies all available bytes (up to max bufsize) from frskyUserData circular
buffer into supplied *buffer. Returns number of bytes copied (or zero)
*/
uint8_t frskyGetUserData(char *buffer, uint8_t bufSize)
{
uint8_t i = 0;
while (!frskyUserData.isEmpty())
{
buffer[i] = frskyUserData.get();
i++;
}
return i;
}
#endif
#ifdef FRSKY_HUB
int8_t parseTelemHubIndex(uint8_t index)
{
@@ -133,7 +152,7 @@ void parseTelemHubByte(uint8_t byte)
((uint8_t*)&frskyHubData)[structPos+1] = byte;
state = TS_IDLE;
}
#endif
#endif
/*
Called from somewhere in the main loop or a low priority interrupt
@@ -465,11 +484,102 @@ void FrskyData::set(uint8_t value)
max = value;
if (!min || min > value)
min = value;
}
}
// TODO not here!
#if defined (PCBV3)
char g_logFilename[21]; // "/G9XLOGS/M00_000.TXT\0" max required length = 21
// These global so we can close any open file from anywhere
FATFS FATFS_Obj;
FIL g_oLogFile;
#endif
void resetTelemetry()
{
memset(frskyTelemetry, 0, sizeof(frskyTelemetry));
memset(frskyRSSI, 0, sizeof(frskyRSSI));
#if defined (PCBV3)
// Determine and set log file filename
FRESULT result;
// close any file left open. E.G. Changing models with log switch still on.
if (g_oLogFile.fs) f_close(&g_oLogFile);
strcpy(g_logFilename, "/G9XLOGS/M00_000.TXT");
uint8_t num = g_eeGeneral.currModel + 1;
char *n = &g_logFilename[11];
*n = (char)((num % 10) + '0');
*(--n) = (char)((num / 10) + '0');
result = f_mount(0, &FATFS_Obj);
if (result!=FR_OK)
{
strcpy(g_logFilename, "FILE SYSTEM ERROR");
}
else
{
// Skip over any existing log files ... _000, _001, etc. (or find first gap in numbering)
while (1)
{
result = f_open(&g_oLogFile, g_logFilename, FA_OPEN_EXISTING | FA_READ);
if (result == FR_OK)
{
f_close(&g_oLogFile);
// bump log file counter (file extension)
n = &g_logFilename[15];
if (++*n > '9')
{
*n='0';
n--;
if (++*n > '9')
{
*n='0';
n--;
if (++*n > '9')
{
*n='0';
break; // Wow. We looped back around past 999 to 000! abort loop
}
}
}
}
else if (result == FR_NO_PATH)
{
if (f_mkdir("/G9XLOGS") != FR_OK)
{
result = FR_NO_PATH;
break;
}
else
continue;
}
else
break;
}
switch (result)
{
case FR_NO_PATH:
strcpy(g_logFilename, "Check /G9XLOGS folder");
break;
case FR_NOT_READY:
strcpy(g_logFilename, "DATA CARD NOT PRESENT");
break;
default:
break;
}
}
// g_logFilename should now be set appropriately.
#endif
}
+12 -2
View File
@@ -451,6 +451,14 @@ void menuProcDiagKeys(uint8_t event)
lcd_putcAtt(5*FW+2, y, t+'0', t);
}
#if defined (PCBV4)
for(uint8_t i=0; i<2; i++) {
uint8_t y = i*FH + FH;
lcd_putsn_P(14*FW, y, PSTR("RE1RE2")+3*i, 3);
lcd_outdezNAtt(18*FW, y, g_rotenc[i], LEFT|(keyState((EnumKeys)(SW_RE1+i)) ? INVERS : 0));
}
#endif
lcd_putsn_P(14*FW, 3*FH, PSTR("Trim- +"), 7);
for(uint8_t i=0; i<4; i++)
{
@@ -474,8 +482,10 @@ void menuProcDiagAna(uint8_t event)
uint8_t y=i*FH;
lcd_putsn_P( 4*FW, y,PSTR("A1A2A3A4A5A6A7A8")+2*i,2);
lcd_outhex4( 8*FW, y,anaIn(i));
if(i<7) lcd_outdez8(17*FW, y, (int32_t)calibratedStick[i]*100/1024);
if(i==7) putsVolts(17*FW, y, g_vbat100mV, (sub==1 ? INVERS : 0));
if(i<7)
lcd_outdez8(17*FW, y, (int32_t)calibratedStick[i]*100/1024);
else
putsVolts(17*FW, y, g_vbat100mV, (sub==1 ? INVERS : 0));
}
// lcd_outdezAtt( 21*FW, 3*FH, g_eeGeneral.vBatCalib, 0) ;
// lcd_outdezAtt( 21*FW, 4*FH, abRunningAvg, 0) ;
+200 -57
View File
@@ -43,8 +43,8 @@ mode4 ail thr ele rud
EEGeneral g_eeGeneral;
ModelData g_model;
uint16_t g_tmr1Latency_max;
uint16_t g_tmr1Latency_min = 0x7ff;
uint8_t g_tmr1Latency_max;
uint8_t g_tmr1Latency_min;
uint16_t g_timeMain;
uint16_t g_time_per10;
@@ -256,12 +256,13 @@ int16_t Expo::expo(int16_t x)
#endif
void applyExpos(int16_t *anas)
void applyExpos(int16_t *anas, uint8_t phase)
{
static int16_t anas2[4]; // values before expo, to ensure same expo base when multiple expo lines are used
memcpy(anas2, anas, sizeof(anas2));
uint8_t phase = getFlightPhase();
if (phase == 255)
phase = getFlightPhase();
int8_t cur_chn = -1;
for (uint8_t i=0; i<DIM(g_model.expoData); i++) {
@@ -448,10 +449,8 @@ void setTrimValue(uint8_t phase, uint8_t idx, int16_t trim)
STORE_MODELVARS;
}
uint8_t getTrimFlightPhase(uint8_t idx, int8_t phase) // TODO uint8_t phase?
uint8_t getTrimFlightPhase(uint8_t idx, uint8_t phase)
{
if (phase == -1) phase = getFlightPhase();
for (uint8_t i=0; i<MAX_PHASES; i++) {
if (phase == 0) return 0;
int16_t trim = getTrimValue(phase, idx);
@@ -674,7 +673,7 @@ uint8_t checkTrim(uint8_t event)
if (k>=0 && k<8) { // && (event & _MSK_KEY_REPT))
//LH_DWN LH_UP LV_DWN LV_UP RV_DWN RV_UP RH_DWN RH_UP
uint8_t idx = k/2;
uint8_t phase = getTrimFlightPhase(idx);
uint8_t phase = getTrimFlightPhase(idx, getFlightPhase());
int16_t before = getTrimValue(phase, idx);
int8_t v = (s==0) ? min(32, abs(before)/4+1) : 1 << (s-1); // 1=>1 2=>2 3=>4 4=>8
bool thro = (((2-(g_eeGeneral.stickMode&1)) == idx) && g_model.thrTrim);
@@ -817,7 +816,7 @@ void getADC_bandgap()
{
#if defined(PCBSTD)
ADMUX=0x1E|ADC_VREF_TYPE; // Switch MUX to internal 1.22V reference
_delay_us(5); // short delay to stablise reference voltage
_delay_us(5); // short delay to stabilise reference voltage
ADCSRA|=0x40;
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10; // grab a sample
@@ -1093,13 +1092,13 @@ int32_t act [MAX_MIXERS] = {0};
uint8_t swOn [MAX_MIXERS] = {0};
uint8_t mixWarning;
inline void evalTrims()
inline void evalTrims(uint8_t phase)
{
for (uint8_t i=0; i<NUM_STICKS; i++) {
// do trim -> throttle trim if applicable
int16_t v = anas[i];
int32_t vv = 2*RESX;
int16_t trim = getTrimValue(getTrimFlightPhase(i), i);
int16_t trim = getTrimValue(getTrimFlightPhase(i, phase), i);
if (IS_THROTTLE(i) && g_model.thrTrim) {
if (g_eeGeneral.throttleReversed)
trim = -trim;
@@ -1113,7 +1112,7 @@ inline void evalTrims()
}
}
uint8_t evalSticks()
uint8_t evalSticks(uint8_t phase)
{
#ifdef HELI
uint16_t d = 0;
@@ -1178,10 +1177,10 @@ uint8_t evalSticks()
}
/* EXPOs */
applyExpos(anas);
applyExpos(anas, phase);
/* TRIMs */
evalTrims();
evalTrims(phase);
return anaCenter;
}
@@ -1204,10 +1203,9 @@ void evalFunctions()
}
}
void perOut(int16_t *chanOut)
void perOut(int16_t *chanOut, uint8_t phase)
{
uint8_t phase = getFlightPhase();
uint8_t anaCenter = evalSticks();
uint8_t anaCenter = evalSticks(phase);
//===========BEEP CENTER================
anaCenter &= g_model.beepANACenter;
@@ -1348,10 +1346,6 @@ void perOut(int16_t *chanOut)
{
#define DEL_MULT 256
//if(init) {
//act[i]=(int32_t)v*DEL_MULT;
//swTog = false;
//}
int16_t diff = v-act[i]/DEL_MULT;
if(swTog) {
@@ -1472,53 +1466,113 @@ void perOut(int16_t *chanOut)
}
}
#ifdef DISPLAY_USER_DATA
char userDataDisplayBuf[TELEM_SCREEN_BUFFER_SIZE];
#endif
void perMain()
{
static uint16_t lastTMR;
tick10ms = (get_tmr10ms() != lastTMR);
lastTMR = get_tmr10ms();
int16_t last_chans512[NUM_CHNOUT];
int16_t next_chans512[NUM_CHNOUT];
static uint8_t last_phase = 0;
#define MAX_ACT 0xffff
static uint16_t fp_act[MAX_PHASES] = {0};
static uint8_t s_fade_flight_phases = 0;
static uint8_t s_last_phase = 255;
uint8_t phase = getFlightPhase();
static uint8_t fading_out_timer = 0;
if (last_phase != phase) {
fading_out_timer = 10 * max(g_model.phaseData[last_phase].fadeOut, g_model.phaseData[phase].fadeIn);
last_phase = phase;
if (s_last_phase != phase) {
if (s_last_phase == 255) {
fp_act[phase] = MAX_ACT;
}
else {
if (g_model.phaseData[s_last_phase].fadeOut) {
s_fade_flight_phases |= (1<<s_last_phase);
}
else {
fp_act[s_last_phase] = 0;
s_fade_flight_phases &= ~(1<<s_last_phase);
}
if (g_model.phaseData[phase].fadeIn) {
s_fade_flight_phases |= (1<<phase);
}
else {
fp_act[phase] = MAX_ACT;
s_fade_flight_phases &= ~(1<<phase);
}
}
s_last_phase = phase;
// printf("s_fade_flight_phases=%d\n", s_fade_flight_phases); fflush(stdout);
}
if (fading_out_timer) {
memcpy(last_chans512, g_chans512, sizeof(g_chans512));
}
int16_t next_chans512[NUM_CHNOUT];
perOut(next_chans512);
for (uint8_t i=0; i<NUM_CHNOUT; i++) {
cli();
if (fading_out_timer) {
g_chans512[i] = last_chans512[i] + (next_chans512[i] - last_chans512[i]) / fading_out_timer;
fading_out_timer--;
if (s_fade_flight_phases) {
int32_t sum_chans512[NUM_CHNOUT] = {0};
int32_t weight = 0;
for (uint8_t p=0; p<MAX_PHASES; p++) {
if (s_fade_flight_phases & (1<<p)) {
perOut(next_chans512, p);
// printf("perOut(%d - %d)=>%d\n", p, fp_act[p], next_chans512[2]);
for (uint8_t i=0; i<NUM_CHNOUT; i++) {
sum_chans512[i] += (int32_t)next_chans512[i] * fp_act[p];
}
weight += fp_act[p];
}
}
// printf("sum=%d, weight=%d ", sum_chans512[2], weight); fflush(stdout);
assert(weight);
for (uint8_t i=0; i<NUM_CHNOUT; i++) {
next_chans512[i] = ((int32_t)sum_chans512[i] / weight);
}
// printf("output = %d\n", next_chans512[2]); fflush(stdout);
}
else {
g_chans512[i] = next_chans512[i];
perOut(next_chans512, phase);
}
for (uint8_t i=0; i<NUM_CHNOUT; i++) {
cli();
g_chans512[i] = next_chans512[i];
sei();
}
#ifdef EEPROM_ASYNC_WRITE
if (!eeprom_buffer_size) {
if (theFile.isWriting())
theFile.nextWriteStep();
else if (s_eeDirtyMsk)
eeCheck();
}
#endif
if(!tick10ms) return; //make sure the rest happen only every 10ms.
if (s_fade_flight_phases) {
for (uint8_t p=0; p<MAX_PHASES; p++) {
// printf("f_act[%d]=%d\n", p, fp_act[p]);
if (s_fade_flight_phases & (1<<p)) {
if (p == phase) {
uint16_t delta = (MAX_ACT / 100) / g_model.phaseData[p].fadeIn;
if (MAX_ACT - fp_act[p] > delta)
fp_act[p] += delta;
else {
fp_act[p] = MAX_ACT;
s_fade_flight_phases -= (1<<p);
}
}
else {
uint16_t delta = (MAX_ACT / 100) / g_model.phaseData[p].fadeOut;
if (fp_act[p] > delta)
fp_act[p] -= delta;
else {
fp_act[p] = 0;
s_fade_flight_phases -= (1<<p);
}
}
}
}
}
evalFunctions();
if (s_noHi) s_noHi--;
@@ -1537,10 +1591,98 @@ void perMain()
if (trimsCheckTimer > 0)
trimsCheckTimer -= 1;
#ifndef EEPROM_ASYNC_WRITE
eeCheck();
#endif
#if defined (FRSKY)
/***** TEST CODE - Fr-Sky SD/MMC card / User Data experiments *****/
#if defined (PCBV3)
/* Use light switch (on) to open telemtry test log file */
static FRESULT result;
static int8_t testLogOpen = 0;
if(getSwitch(g_eeGeneral.lightSw,0))
{
// while(1); // Test WDT
if ((testLogOpen==0) // if we know we haven't started logging ...
|| ((testLogOpen==1) && !g_oLogFile.fs)) // ... or we thought we had, but the file got closed
{
result = f_mount(0, &FATFS_Obj);
if (result!=FR_OK)
{
testLogOpen = -1;
beepAgain = result - 1;
beepKey();
}
else
{
// create new log file using filename set up in pers.cpp::resetTelemetry()
result = f_open(&g_oLogFile, g_logFilename, FA_OPEN_ALWAYS | FA_WRITE);
if (result!=FR_OK)
{
testLogOpen = -2;
beepAgain = result - 1;
beepKey();
}
else
{
f_lseek(&g_oLogFile, g_oLogFile.fsize); // append
testLogOpen = 1;
beepWarn2();
}
}
}
}
else
{
if (testLogOpen==1)
{
f_close(&g_oLogFile);
beepWarn2();
}
testLogOpen = 0;
}
#ifdef DISPLAY_USER_DATA
////////////////
// Write raw user data into on-screen display line buffer
char userDataRxBuffer[21]; // Temp buffer used to collect fr-sky user data
// retrieve bytes from user data buffer and insert into display string,
// scrolling at the 21 character mark (edge of screen)
uint8_t numbytes = frskyGetUserData(userDataRxBuffer, 21); // Get as many bytes as we can
static uint8_t displayBufferIndex;
for (uint8_t byt=0; byt < numbytes; byt++)
{
displayBufferIndex++;
if (displayBufferIndex > 20)
{
for (int xx=0; xx<20; xx++) // scroll one char left
userDataDisplayBuf[xx] = userDataDisplayBuf[xx+1];
displayBufferIndex = 20;
}
userDataDisplayBuf[displayBufferIndex] = userDataRxBuffer[byt];
// Write the raw byte out to log file, if open
if (testLogOpen && (g_oLogFile.fs != 0))
f_putc(userDataRxBuffer[byt], &g_oLogFile);
}
////////////////
#endif
/***** END TEST CODE - Fr-Sky User Data experiments *****/
// PCBV3
#endif
// FRSKY
#endif
lcd_clear();
uint8_t evt=getEvent();
evt = checkTrim(evt);
@@ -1950,22 +2092,23 @@ uint16_t DEBUG2 = 0;
void instantTrim()
{
uint8_t phase = getFlightPhase();
for (uint8_t i=0; i<NUM_STICKS; i++) {
if (!IS_THROTTLE(i)) {
// don't instant trim the throttle stick
uint8_t phase = getTrimFlightPhase(i);
uint8_t trim_phase = getTrimFlightPhase(i, phase);
s_noStickInputs = true;
evalSticks();
evalSticks(phase);
s_noStickInputs = false;
int16_t trim = (anas[i] + trims[i]) / 2;
// printf("anas[%d]=%d, trims[%d]=%d, trim=%d, subtrim=%d => trim=%d\n", i, anas[i], i, trims[i], g_model.phaseData[phase].trim[i], g_model.subtrim[i], trim);
if (trim < TRIM_EXTENDED_MIN) {
trim = TRIM_EXTENDED_MIN;
}
if (trim > TRIM_EXTENDED_MAX) {
trim = TRIM_EXTENDED_MAX;
}
setTrimValue(phase, i, trim);
setTrimValue(trim_phase, i, trim);
}
}
@@ -1978,7 +2121,7 @@ void moveTrimsToOffsets() // copy state of 3 primary to subtrim
int16_t zero_chans512[NUM_CHNOUT];
s_noStickInputs = true;
perOut(zero_chans512); // do output loop - zero input sticks
perOut(zero_chans512, getFlightPhase()); // do output loop - zero input sticks
s_noStickInputs = false;
for (uint8_t i=0; i<NUM_CHNOUT; i++)
@@ -2001,27 +2144,27 @@ void moveTrimsToOffsets() // copy state of 3 primary to subtrim
#if defined (PCBV4)
// Rotary encoder interrupts
uint8_t volatile g_rotenc1, g_rotenc2 = 0;
volatile uint8_t g_rotenc[2] = {0};
ISR(INT2_vect)
{
uint8_t input = PIND & 0b00001100;
if (input == 0 || input == 0b00001100) g_rotenc1--;
if (input == 0 || input == 0b00001100) g_rotenc[0]--;
}
ISR(INT3_vect)
{
uint8_t input = PIND & 0b00001100;
if (input == 0 || input == 0b00001100) g_rotenc1++;
if (input == 0 || input == 0b00001100) g_rotenc[0]++;
}
ISR(INT5_vect)
{
uint8_t input = PINE & 0b01100000;
if (input == 0 || input == 0b01100000) g_rotenc2++;
if (input == 0 || input == 0b01100000) g_rotenc[1]++;
}
ISR(INT6_vect)
{
uint8_t input = PINE & 0b01100000;
if (input == 0 || input == 0b01100000) g_rotenc2--;
if (input == 0 || input == 0b01100000) g_rotenc[1]--;
}
#endif
@@ -2188,7 +2331,7 @@ int main(void)
clearKeyEvents(); //make sure no keys are down before proceeding
perOut(g_chans512);
perOut(g_chans512, getFlightPhase());
lcdSetRefVolt(g_eeGeneral.contrast);
g_LightOffCounter = g_eeGeneral.lightAutoOff*500; //turn on light for x seconds - no need to press key Issue 152
+19 -12
View File
@@ -29,6 +29,7 @@
#include <string.h>
#if defined(PCBV3)
#include "ff.h"
#include "time.h"
#endif
@@ -291,7 +292,9 @@ enum EnumKeys {
SW_ID2 ,
SW_AileDR ,
SW_Gear ,
SW_Trainer
SW_Trainer,
SW_RE1,
SW_RE2
};
#define CURVE_BASE 7
@@ -451,10 +454,6 @@ void per10ms();
/// Erzeugt periodisch alle Outputs ausser Bildschirmausgaben.
void zeroVariables();
#define NO_TRAINER 0x01
#define NO_INPUT 0x02
extern void perOut(int16_t *chanOut, uint8_t att);
/// Liefert den Zustand des Switches 'swtch'. Die Numerierung erfolgt ab 1
/// (1=SW_ON, 2=SW_ThrCt, 10=SW_Trainer). 0 Bedeutet not conected.
/// Negative Werte erzeugen invertierte Ergebnisse.
@@ -474,7 +473,7 @@ bool getSwitch(int8_t swtch, bool nc);
///
uint8_t getFlightPhase();
uint8_t getTrimFlightPhase(uint8_t idx, int8_t phase=-1);
uint8_t getTrimFlightPhase(uint8_t idx, uint8_t phase);
extern int16_t getTrimValue(uint8_t phase, uint8_t idx);
extern void setTrimValue(uint8_t phase, uint8_t idx, int16_t trim);
@@ -498,8 +497,8 @@ extern uint8_t Timer2_running ;
extern uint16_t timer2 ;
void resetTimer2() ;
extern uint16_t g_tmr1Latency_max;
extern uint16_t g_tmr1Latency_min;
extern uint8_t g_tmr1Latency_max;
extern uint8_t g_tmr1Latency_min;
extern uint16_t g_timeMain;
extern uint16_t g_time_per10;
@@ -560,15 +559,13 @@ template<class t> inline t limit(t mi, t x, t ma){ return min(max(mi,x),ma); }
/// eeCheck ins EEPROM zurueckgeschrieben.
void eeWriteBlockCmp(const void *i_pointer_ram, void *i_pointer_eeprom, size_t size);
void eeDirty(uint8_t msk);
#ifdef EEPROM_ASYNC_WRITE
inline void eeFlush() { theFile.flush(); }
#endif
void eeCheck(bool immediately=false);
void eeReadAll();
bool eeModelExists(uint8_t id);
uint16_t eeLoadModelName(uint8_t id, char *name);
void eeLoadModel(uint8_t id);
int8_t eeDuplicateModel(uint8_t id, bool down=true);
int8_t eeFindEmptyModel(uint8_t id, bool down);
///number of real input channels (1-9) plus virtual input channels X1-X4
#define NUM_XCHNRAW (NUM_STICKS+NUM_POTS+2/*MAX/FULL*/+3/*CYC1-CYC3*/+NUM_PPM+NUM_CHNOUT+NUM_TELEMETRY)
@@ -651,7 +648,7 @@ extern uint16_t expou(uint16_t x, uint16_t k);
extern int16_t expo(int16_t x, int16_t k);
extern int16_t intpol(int16_t, uint8_t);
extern int16_t applyCurve(int16_t, uint8_t, uint8_t srcRaw);
extern void applyExpos(int16_t *anas);
extern void applyExpos(int16_t *anas, uint8_t phase=255);
extern uint16_t anaIn(uint8_t chan);
extern int16_t calibratedStick[7];
@@ -729,11 +726,21 @@ inline bool isFunctionActive(uint8_t func)
return active_functions & (1 << (func-1));
}
#ifdef DISPLAY_USER_DATA
#define TELEM_SCREEN_BUFFER_SIZE 21
extern char userDataDisplayBuf[TELEM_SCREEN_BUFFER_SIZE]; // text buffer for frsky telem. user data experiments
#endif
#if defined (PCBV3)
extern char g_logFilename[21]; // pers.cpp::resetTelemetry()
extern FATFS FATFS_Obj; // pers.cpp::resetTelemetry()
extern FIL g_oLogFile; // pers.cpp::resetTelemetry()
#endif
#if defined (PCBV4)
// Global rotary encoder registers -- 8-bit, 0-255
extern volatile uint8_t g_rotenc[2];
#endif
#endif // gruvin9x_h
/*eof*/
+9 -2
View File
@@ -140,7 +140,7 @@ TEST(EEPROM, eeCheckImmediately) {
EXPECT_EQ(sz, 300);
}
TEST(EEPROM, eeDuplicateModel) {
TEST(EEPROM, copy) {
eepromFile = NULL; // in memory
uint8_t buf[1000];
@@ -151,7 +151,7 @@ TEST(EEPROM, eeDuplicateModel) {
theFile.writeRlc(5, 6, buf, 300, true);
eeDuplicateModel(4);
theFile.copy(6, 5);
theFile.openRd(6);
uint16_t sz=0;
@@ -250,6 +250,13 @@ TEST(getSwitch, circularCSW) {
EXPECT_EQ(getSwitch(-(1+MAX_SWITCH-NUM_CSW), 0), true);
}
TEST(getSwitch, nullSW) {
memset(&g_model, 0, sizeof(g_model));
EXPECT_EQ(getSwitch(0, 0), false);
EXPECT_EQ(getSwitch(0, true), true);
EXPECT_EQ(getSwitch(0, 0), false);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
+1 -1
View File
@@ -451,7 +451,7 @@ void putsFlightPhase(uint8_t x, uint8_t y, int8_t idx, uint8_t att)
{
if (idx==0) { lcd_putsAtt(x,y,PSTR("---"),att); return; }
if (idx < 0) { lcd_vlineStip(x-2, y, 8, 0x5E/*'!'*/); idx = -idx; }
putsStrIdx(x, y, PSTR("FP"), idx, att);
putsStrIdx(x, y, PSTR("FP"), idx-1, att);
}
#define CURV_STR "---x>0x<0|x|f>0f<0|f|"
+76 -83
View File
@@ -148,10 +148,8 @@ void menuProcModelSelect(uint8_t event)
TITLE("MODELSEL");
#ifdef EEPROM_ASYNC_WRITE
// flush eeprom write
eeFlush();
#endif
// flush eeprom write
eeFlush();
if (s_confirmation) {
EFile::rm(FILE_MODEL(m_posVert)); // delete file
@@ -180,7 +178,7 @@ void menuProcModelSelect(uint8_t event)
{
case EVT_ENTRY:
m_posVert = sub = g_eeGeneral.currModel;
s_copyMode = 0;
s_copyMode = 0; // TODO only this one?
s_copyTgtOfs = 0;
s_copySrcRow = -1;
break;
@@ -192,68 +190,58 @@ void menuProcModelSelect(uint8_t event)
}
// no break
case EVT_KEY_BREAK(KEY_EXIT):
if (s_copyTgtOfs || s_copySrcRow >= 0) {
eeCheck(true); // force writing of current model data before this is changed
do {
if (s_copyTgtOfs < 0) {
s_copyTgtOfs++;
m_posVert = (MAX_MODELS+m_posVert-1) % MAX_MODELS;
}
else {
s_copyTgtOfs--;
m_posVert = (m_posVert+1) % MAX_MODELS;
}
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = true;
#endif
EFile::swap(FILE_MODEL(sub), FILE_MODEL(m_posVert));
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = false;
#endif
if (m_posVert == g_eeGeneral.currModel) {
g_eeGeneral.currModel = sub;
STORE_GENERALVARS;
}
else if (sub == g_eeGeneral.currModel) {
g_eeGeneral.currModel = m_posVert;
STORE_GENERALVARS;
}
sub = m_posVert;
} while (s_copyTgtOfs != 0);
if (s_copySrcRow >= 0) {
EFile::rm(FILE_MODEL(sub));
sub = m_posVert = s_copySrcRow;
s_copySrcRow = -1;
}
if (s_copyMode) {
sub = m_posVert = (s_copyMode == MOVE_MODE || s_copySrcRow<0) ? (16+sub+s_copyTgtOfs) % 16 : s_copySrcRow; // TODO reset s_copySrcRow?
s_copyMode = 0; // TODO only this one?
s_copySrcRow = -1;
s_copyTgtOfs = 0;
killEvents(_event);
}
s_copyMode = 0;
killEvents(_event);
break;
case EVT_KEY_BREAK(KEY_MENU):
if (s_copyTgtOfs || s_copySrcRow >= 0) {
s_copyMode = 0;
}
else if (EFile::exists(FILE_MODEL(sub))) {
s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
}
s_copySrcRow = -1;
s_copyTgtOfs = 0;
break;
case EVT_KEY_LONG(KEY_MENU):
if (s_copyTgtOfs) {
case EVT_KEY_BREAK(KEY_MENU):
if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) {
eeCheck(true); // force writing of current model data before this is changed
uint8_t cur = (16 + sub + s_copyTgtOfs) % 16;
if (s_copyMode == COPY_MODE) {
if (!theFile.copy(FILE_MODEL(cur), FILE_MODEL(s_copySrcRow)))
cur = sub;
}
s_copySrcRow = g_eeGeneral.currModel; // to update the currModel value
while (sub != cur) {
uint8_t src = cur;
cur = (s_copyTgtOfs > 0 ? cur+15 : cur+1) % 16;
EFile::swap(FILE_MODEL(src), FILE_MODEL(cur));
if (src == s_copySrcRow)
s_copySrcRow = cur;
else if (cur == s_copySrcRow)
s_copySrcRow = src;
}
if (s_copySrcRow != g_eeGeneral.currModel) {
g_eeGeneral.currModel = s_copySrcRow;
STORE_GENERALVARS;
}
s_copyMode = 0; // TODO only this one?
s_copySrcRow = -1;
s_copyTgtOfs = 0;
s_copyMode = 0;
}
else {
else if (_event == EVT_KEY_LONG(KEY_MENU)) {
eeCheck(true); // force writing of current model data before this is changed
if (g_eeGeneral.currModel != sub) {
g_eeGeneral.currModel = sub;
STORE_GENERALVARS;
eeLoadModel(sub);
}
eeLoadModel(sub);
killEvents(event);
}
else if (EFile::exists(FILE_MODEL(sub))) {
s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
}
killEvents(_event);
break;
case EVT_KEY_FIRST(KEY_LEFT):
case EVT_KEY_FIRST(KEY_RIGHT):
@@ -266,41 +254,25 @@ void menuProcModelSelect(uint8_t event)
case EVT_KEY_FIRST(KEY_UP):
case EVT_KEY_FIRST(KEY_DOWN):
if (s_copyMode) {
eeCheck(true);
int8_t next_ofs = (_event == EVT_KEY_FIRST(KEY_UP) ? s_copyTgtOfs+1 : s_copyTgtOfs-1);
if (next_ofs == 16 || next_ofs == -16)
next_ofs = 0;
if (s_copySrcRow < 0 && s_copyMode==COPY_MODE) {
s_copySrcRow = oldSub;
// insert a model (in the first empty slot above / below)
m_posVert = eeDuplicateModel(s_copySrcRow, _event==EVT_KEY_FIRST(KEY_DOWN));
// find a hole (in the first empty slot above / below)
m_posVert = eeFindEmptyModel(s_copySrcRow, _event==EVT_KEY_FIRST(KEY_DOWN));
if (m_posVert == (uint8_t)-1) {
// no free room for duplicating the model
beepWarn();
m_posVert = oldSub;
s_copyMode = 0;
s_copyMode = 0; // TODO only this one?
s_copyTgtOfs = 0;
s_copySrcRow = -1;
}
next_ofs = 0;
sub = m_posVert;
}
else {
// only swap the model with its neighbor
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = true;
#endif
EFile::swap(FILE_MODEL(oldSub), FILE_MODEL(sub));
#ifdef EEPROM_ASYNC_WRITE
s_sync_write = false;
#endif
if (oldSub == g_eeGeneral.currModel) {
g_eeGeneral.currModel = sub;
STORE_GENERALVARS;
}
else if (sub == g_eeGeneral.currModel) {
g_eeGeneral.currModel = oldSub;
STORE_GENERALVARS;
}
}
s_copyTgtOfs = next_ofs;
}
break;
@@ -308,21 +280,42 @@ void menuProcModelSelect(uint8_t event)
if (sub-s_pgOfs < 1) s_pgOfs = max(0, sub-1);
else if (sub-s_pgOfs > 5) s_pgOfs = min(MAX_MODELS-7, sub-4);
// printf("copy_mode=%d s_copySrcRow=%d s_copyTgtOfs=%d sub=%d\n", s_copyMode, s_copySrcRow, s_copyTgtOfs, sub); fflush(stdout);
for (uint8_t i=0; i<7; i++) {
uint8_t y=(i+1)*FH;
uint8_t k=i+s_pgOfs;
lcd_outdezNAtt(3*FW+2, y, k+1, LEADING0+((!s_copyMode && sub==k) ? INVERS : 0), 2);
if (s_copyMode == MOVE_MODE || (s_copyMode == COPY_MODE && s_copySrcRow >= 0)) {
if (k == sub) {
if (s_copyMode == COPY_MODE) {
k = s_copySrcRow;
lcd_putc(20*FW+2, y, '+');
}
else {
k = sub + s_copyTgtOfs;
}
}
else if (s_copyTgtOfs < 0 && ((k < sub && k >= sub+s_copyTgtOfs) || (k-16 < sub && k-16 >= sub+s_copyTgtOfs)))
k += 1;
else if (s_copyTgtOfs > 0 && ((k > sub && k <= sub+s_copyTgtOfs) || (k+16 > sub && k+16 <= sub+s_copyTgtOfs)))
k += 15;
}
k %= 16;
if (EFile::exists(FILE_MODEL(k))) {
uint16_t size = eeLoadModelName(k, name);
putsModelName(4*FW, y, name, k, 0);
lcd_outdezAtt(20*FW, y, size, 0);
if (k==g_eeGeneral.currModel && (s_copySrcRow<0 || i+s_pgOfs!=sub)) lcd_putc(1, y, '*');
}
if (k==g_eeGeneral.currModel) lcd_putc(1, y, '*');
if (s_copyMode && k==sub) {
if (s_copyMode == COPY_MODE)
lcd_putc(20*FW+2, y, '+');
lcd_rect(8, y-1, DISPLAY_W-1-7, 9, s_copyMode == COPY_MODE ? 0xff : 0x55);
if (s_copyMode && sub==i+s_pgOfs) {
lcd_filled_rect(9, y, DISPLAY_W-1-9, 7);
lcd_rect(8, y-1, DISPLAY_W-1-7, 9, s_copyMode == COPY_MODE ? 0xff : 0x55);
}
}
+9 -81
View File
@@ -29,9 +29,6 @@
RlcFile theFile; //used for any file operation
#define FILE_TYP_GENERAL 1
#define FILE_TYP_MODEL 2
void generalDefault()
{
memset(&g_eeGeneral,0,sizeof(g_eeGeneral));
@@ -49,9 +46,7 @@ void generalDefault()
g_eeGeneral.calibSpanNeg[i] = 0x180;
g_eeGeneral.calibSpanPos[i] = 0x180;
}
int16_t sum=0;
for(int i=0; i<12;i++) sum+=g_eeGeneral.calibMid[i];
g_eeGeneral.chkSum = sum;
g_eeGeneral.chkSum = (0x200 * 7) + (0x180 * 5);
}
#ifdef TRANSLATIONS
@@ -287,6 +282,13 @@ void eeLoadModel(uint8_t id)
theFile.openRlc(FILE_MODEL(id));
uint16_t sz = theFile.readRlc((uint8_t*)&g_model, sizeof(g_model));
#ifdef SIMU
if (sz > 0 && sz != sizeof(g_model)) {
printf("Model data read=%d bytes vs %d bytes\n", sz, sizeof(ModelData));
fflush(stdout);
}
#endif
if (sz != sizeof(ModelData)) {
// alert("Error Loading Model");
modelDefault(id);
@@ -302,7 +304,7 @@ void eeLoadModel(uint8_t id)
}
}
int8_t eeDuplicateModel(uint8_t id, bool down)
int8_t eeFindEmptyModel(uint8_t id, bool down)
{
int8_t i = id;
for (;;) {
@@ -310,25 +312,6 @@ int8_t eeDuplicateModel(uint8_t id, bool down)
if (!EFile::exists(FILE_MODEL(i))) break;
if (i == id) return -1; // no free space in directory left
}
EFile theFile2;
theFile2.openRd(FILE_MODEL(id));
#ifdef EEPROM_ASYNC_WRITE
theFile.create(FILE_MODEL(i), FILE_TYP_MODEL, true);
#else
theFile.create(FILE_MODEL(i), FILE_TYP_MODEL, 600);
#endif
uint8_t buf[15];
uint8_t len;
while((len=theFile2.read(buf, 15)))
{
theFile.write(buf, len);
if (errno() != 0) {
return false;
}
}
theFile.close();
return i;
}
@@ -346,20 +329,11 @@ void eeReadAll()
generalDefault();
//alert(PSTR("default ok"));
#ifdef EEPROM_ASYNC_WRITE
theFile.writeRlc(FILE_GENERAL, FILE_TYP_GENERAL,(uint8_t*)&g_eeGeneral,sizeof(EEGeneral), true);
#else
uint16_t sz = theFile.writeRlc(FILE_GENERAL,FILE_TYP_GENERAL,(uint8_t*)&g_eeGeneral,sizeof(EEGeneral), 200);
if(sz!=sizeof(EEGeneral)) alert(PSTR("genwrite error"));
#endif
modelDefault(0);
//alert(PSTR("modef ok"));
#ifdef EEPROM_ASYNC_WRITE
theFile.writeRlc(FILE_MODEL(0), FILE_TYP_MODEL, (uint8_t*)&g_model, sizeof(g_model), true);
#else
theFile.writeRlc(FILE_MODEL(0), FILE_TYP_MODEL, (uint8_t*)&g_model, sizeof(g_model),200);
#endif
//alert(PSTR("modwrite ok"));
}
@@ -368,22 +342,13 @@ void eeReadAll()
uint8_t s_eeDirtyMsk;
#ifndef EEPROM_ASYNC_WRITE
static uint16_t s_eeDirtyTime10ms;
#define WRITE_DELAY_10MS 100
#endif
void eeDirty(uint8_t msk)
{
s_eeDirtyMsk |= msk;
#ifndef EEPROM_ASYNC_WRITE
if (msk)
s_eeDirtyTime10ms = get_tmr10ms();
#endif
}
void eeCheck(bool immediately)
{
#ifdef EEPROM_ASYNC_WRITE
if (immediately) {
eeFlush();
}
@@ -396,41 +361,4 @@ void eeCheck(bool immediately)
s_eeDirtyMsk = 0;
theFile.writeRlc(FILE_MODEL(g_eeGeneral.currModel), FILE_TYP_MODEL, (uint8_t*)&g_model, sizeof(g_model), immediately);
}
#else
uint8_t msk = s_eeDirtyMsk;
if (!msk) return;
if( !immediately && ((get_tmr10ms() - s_eeDirtyTime10ms) < WRITE_DELAY_10MS)) return;
s_eeDirtyMsk = 0;
if(msk & EE_GENERAL){
if(theFile.writeRlc(FILE_TMP, FILE_TYP_GENERAL, (uint8_t*)&g_eeGeneral,
sizeof(EEGeneral),20) == sizeof(EEGeneral))
{
EFile::swap(FILE_GENERAL,FILE_TMP);
}else{
if(errno()==ERR_TMO){
s_eeDirtyMsk |= EE_GENERAL; //try again
s_eeDirtyTime10ms = get_tmr10ms() - WRITE_DELAY_10MS;
}else{
alert(PSTR("EEPROM overflow"));
}
}
//first finish GENERAL, then MODEL !!avoid Toggle effect
}
if(msk & EE_MODEL){
if(theFile.writeRlc(FILE_TMP, FILE_TYP_MODEL, (uint8_t*)&g_model,
sizeof(g_model),20) == sizeof(g_model))
{
EFile::swap(FILE_MODEL(g_eeGeneral.currModel),FILE_TMP);
}else{
if(errno()==ERR_TMO){
s_eeDirtyMsk |= EE_MODEL; //try again
s_eeDirtyTime10ms = get_tmr10ms() - WRITE_DELAY_10MS;
}else{
alert(PSTR("EEPROM overflow"));
}
}
}
//beepWarn1();
#endif
}