/dev/batt Doesn't Exist On F200? Any Alternative?


naomaru

Still Fresh
Joined
Dec 3, 2007
Messages
8
Hi,

To get battery charge level on F200, I tried reading /dev/batt device, as described here:
http://wiki.gp2x.org/wiki/Devbatt

Unfortunately, open("/dev/batt", O_RDONLY) returns -1 (ENOFILE) because /dev/batt doesn't exist on my F200. "ls -l /dev" confirmed this.

Does this mean there's no way to get a battery charge level on F200? Or are there any alternatives?

Standard gp2x menu shows a battery icon with charge level, so I guess there's some way ...

Any help shall be appreciated. Thanks.
 
Now it's in the right forum :)

I think GPH removed the battery checking circuitry from the F200 as there "low battery level" light was inconsistent and sometimes completely wrong. To see if they just removed it from the kernel however, scan the analog input ports of the processor as thats where they used to place it (with 10-bit conversion if I remember correctly).
 
Squidge said:
Now it's in the right forum :)

I think GPH removed the battery checking circuitry from the F200 as there "low battery level" light was inconsistent and sometimes completely wrong. To see if they just removed it from the kernel however, scan the analog input ports of the processor as thats where they used to place it (with 10-bit conversion if I remember correctly).
Squidge,

The kernel source (in 4.0.0) for that functionality doesn't compile... I did actually wonder if that was the reason they removed the LED from the final design too ;-)
 
Last edited by a moderator:
Thanks, everyone,

Both gp2xmenu and mplayer (on option panel) on F200 have a battery indicator, so there must be some way to obtain battery charge information from software. Unfortuantely, source code is not available for either gp2xmenu or mplayer for F200, so I can't figure out how ...

There seems to exist a character driver for /dev/batt exists in Firmware 4.0.0 (drivers/char/mmsp2_batt.c). However, hacking kernel on F200 looks too dangerous and difficult, because I can't telnet to F200 ...

Any idea??

simonb said:
Squidge said:
Now it's in the right forum :)

I think GPH removed the battery checking circuitry from the F200 as there "low battery level" light was inconsistent and sometimes completely wrong. To see if they just removed it from the kernel however, scan the analog input ports of the processor as thats where they used to place it (with 10-bit conversion if I remember correctly).
Squidge,

The kernel source (in 4.0.0) for that functionality doesn't compile... I did actually wonder if that was the reason they removed the LED from the final design too ;-)
 
Last edited by a moderator:
OK, I solved it - somewhat.

Although it doesn't have /dev/batt, F200 still has /dev/mssp2adc, which gives you 4 level power indicator: high/mid/low/empty. It's not as detailed as /dev/batt, but sufficient for my app.

When opened and read, /dev/mssp2adc returns 4 byte structure of:

typedef struct {
unsigned short batt;
unsigned short remocon;
} MMSP2ADC;

The value batt has one of the following:
#define BATT_LEVEL_HIGH 0
#define BATT_LEVEL_MID 1
#define BATT_LEVEL_LOW 2
#define BATT_LEVEL_EMPTY 3

Sample code on how to read this is as follows:

typedef struct {
unsigned short batt;
unsigned short remocon;
} MMSP2ADC;

int mmsp2adc(void)
{
int fd, rv;
MMSP2ADC val;
fd = open("/dev/mmsp2adc", O_RDONLY);
//printf ("fd %d\n", fd);
if (fd < 0) {
fprintf (stderr, "cannot open /dev/mmsp2adc, errno = %d\n", errno);
return -1;
}
rv = read (fd, &val, sizeof(MMSP2ADC));
//printf ("rv %d, val.batt %d, val.remocon %d\n", rv, val.batt, val.remocon);
close (fd);
return val.batt;
}

You have to do ioctl() to get the legitimate value for val.remocon. But for now, I only care about the value in val.batt.

Thanks,

naomaru said:
Thanks, everyone,

Both gp2xmenu and mplayer (on option panel) on F200 have a battery indicator, so there must be some way to obtain battery charge information from software. Unfortuantely, source code is not available for either gp2xmenu or mplayer for F200, so I can't figure out how ...

There seems to exist a character driver for /dev/batt exists in Firmware 4.0.0 (drivers/char/mmsp2_batt.c). However, hacking kernel on F200 looks too dangerous and difficult, because I can't telnet to F200 ...

Any idea??

simonb said:
Squidge said:
Now it's in the right forum :)

I think GPH removed the battery checking circuitry from the F200 as there "low battery level" light was inconsistent and sometimes completely wrong. To see if they just removed it from the kernel however, scan the analog input ports of the processor as thats where they used to place it (with 10-bit conversion if I remember correctly).
Squidge,

The kernel source (in 4.0.0) for that functionality doesn't compile... I did actually wonder if that was the reason they removed the LED from the final design too ;-)
 
Last edited by a moderator:
QUOTE

Squidge,

The kernel source (in 4.0.0) for that functionality doesn't compile



naomaru said:
OK, I solved it - somewhat.
So, did you not understand my reply, or just decided to ignore it? :)
 
Last edited by a moderator:
Although it seems to work, this code is extremely slow compared to reading /dev/batt. In lgpt, reading it constantly in the playback loop breaks the smoothness of the program.

Is there any alternative or do I need to check it only 'so often' ?

Thanks
Marc.

naomaru said:
OK, I solved it - somewhat.

Although it doesn't have /dev/batt, F200 still has /dev/mssp2adc, which gives you 4 level power indicator: high/mid/low/empty. It's not as detailed as /dev/batt, but sufficient for my app.

When opened and read, /dev/mssp2adc returns 4 byte structure of:

typedef struct {
unsigned short batt;
unsigned short remocon;
} MMSP2ADC;

The value batt has one of the following:
#define BATT_LEVEL_HIGH 0
#define BATT_LEVEL_MID 1
#define BATT_LEVEL_LOW 2
#define BATT_LEVEL_EMPTY 3

Sample code on how to read this is as follows:

typedef struct {
unsigned short batt;
unsigned short remocon;
} MMSP2ADC;

int mmsp2adc(void)
{
int fd, rv;
MMSP2ADC val;
fd = open("/dev/mmsp2adc", O_RDONLY);
//printf ("fd %d\n", fd);
if (fd < 0) {
fprintf (stderr, "cannot open /dev/mmsp2adc, errno = %d\n", errno);
return -1;
}
rv = read (fd, &val, sizeof(MMSP2ADC));
//printf ("rv %d, val.batt %d, val.remocon %d\n", rv, val.batt, val.remocon);
close (fd);
return val.batt;
}

You have to do ioctl() to get the legitimate value for val.remocon. But for now, I only care about the value in val.batt.

Thanks,

naomaru said:
Thanks, everyone,

Both gp2xmenu and mplayer (on option panel) on F200 have a battery indicator, so there must be some way to obtain battery charge information from software. Unfortuantely, source code is not available for either gp2xmenu or mplayer for F200, so I can't figure out how ...

There seems to exist a character driver for /dev/batt exists in Firmware 4.0.0 (drivers/char/mmsp2_batt.c). However, hacking kernel on F200 looks too dangerous and difficult, because I can't telnet to F200 ...

Any idea??

simonb said:
Squidge said:
Now it's in the right forum :)

I think GPH removed the battery checking circuitry from the F200 as there "low battery level" light was inconsistent and sometimes completely wrong. To see if they just removed it from the kernel however, scan the analog input ports of the processor as thats where they used to place it (with 10-bit conversion if I remember correctly).
Squidge,

The kernel source (in 4.0.0) for that functionality doesn't compile... I did actually wonder if that was the reason they removed the LED from the final design too ;-)
 
Last edited by a moderator:
*moves from his post to this one*
hi i've been doing some "research", and i have found that the only diference between drivers/char/mmsp2_ADC.c and drivers/char/mmsp2_batt.c y that ADC takes the average from 10 values and then converts it to 0 1 2 and 3 depending on the value, if at any moment the last 4 are equal it just returns the last.

Code:
(just BATT_MODE: part)
                tempval = TPC_GetStaticADCOut( 0 ) + inc_val;  //inc_val is used to correct the value being lower because of the higher power consuption while playing a movie or playing some game (GAME_MODE and MOVIE_MOVE defines are 0x10 and 0x22 respectively)
    
                if( tempval > BATT_HIGH_LIMIT) cmode_old = BATT_LEVEL_HIGH;
                else if( tempval > BATT_MID_LIMIT) cmode_old = BATT_LEVEL_MID;
                else if( tempval > BATT_LOW_LIMIT) cmode_old = BATT_LEVEL_LOW;
                else cmode_old = BATT_LEVEL_EMPTY;
    
                while(cnt++ < 10)
                {
                    TPC_SetDefaultSW( 0 );
                    udelay(20);
                    tempval = TPC_GetStaticADCOut( 0 ) + inc_val;
    
                    if( tempval > BATT_HIGH_LIMIT) cmode = BATT_LEVEL_HIGH;
                    else if( tempval > BATT_MID_LIMIT) cmode = BATT_LEVEL_MID;
                    else if( tempval > BATT_LOW_LIMIT) cmode = BATT_LEVEL_LOW;
                    else cmode = BATT_LEVEL_EMPTY;
    
                    if(ccnt == 4){
                        adcVal.batt = cmode;
                        break;
                    }
                    else
                    {
                        if(cmode == cmode_old) ccnt++;
                        else ccnt=0;
                    }
    
                    adcVal.batt = BATT_LEVEL_OLD_STATUS;
                    cmode_old = cmode;
                }
                if (PosAdc == BATT_MODE) break;
    ...
        TPC_SetDefaultSW ( TPC_PU_SW );

VS

Code:
static ssize_t mmsp2_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
    {
        unsigned short getAdc=0;
        // Read ADC    X
        TPC_SetInterruptEnable(0);
    
        udelay(10);
        TPC_SetDefaultSW( 0 );
        udelay(10);
        getAdc = TPC_GetStaticADCOut( 0 );
    
        TPC_SetDefaultSW ( TPC_PU_SW ); /* ¿©±æ ÌũÇÏÀÚ */
        udelay(10);
    
        if(copy_to_user(buf, &getAdc, sizeof(unsigned short)))
        {
            return -EFAULT;
        }
    
        return sizeof(unsigned short);
    }

so it's just a matter of compiling the batt module and load it at startup (as with the mmuhack) (sadly i've never done this before, but still i'm going to give it a try and see if google (or you if you want... :D ) helpme get thi compiled.

EDIT: well i made a program to "reemplace" /dev/batt, what it does is mknod /dev/batt, create a new ./batt and then mount bind them, then just write the teorical value to ./batt.
batterytest seems to work, oldplay doesn't, nor does open2x's CompatMode's menu(when you enter the to the battery meter section it freezes) (need more programs that read the battery, any sugestion?)

teorical values....
Code:
/*
  ** Battery levels
  */
  #define BATT_LEVEL_HIGH 0
  #define BATT_LEVEL_MID 1
  #define BATT_LEVEL_LOW 2
  #define BATT_LEVEL_EMPTY 3
  
  /*
  ** OLD style values
  ** used squidge's values fount at gp2xwiki for this
  */
  #define BATT_OLD_LEVEL_HIGH 800
  #define BATT_OLD_LEVEL_MID 730
  #define BATT_OLD_LEVEL_LOW 630
  #define BATT_OLD_LEVEL_EMPTY 600

Program (with source code): http://ifile.it/k90ztho/GP2X_F200_Battery_Reader.tar

PS: strangely i can't make the new batt file directly in /dev, even if the devfs is mounted as rw.
Code:
none on /dev type devfs (rw)
 sh-3.2# touch batt
 touch: batt: Permission denied
 
Back
Top