espruino / Espruino

The Espruino JavaScript interpreter - Official Repo
http://www.espruino.com/
Other
2.73k stars 741 forks source link

Add "Bangle.touchRd()" and "Bangle.touchWr()" #2525

Closed d3nd3 closed 6 days ago

d3nd3 commented 1 week ago

This one was missing, felt like it should be there for completion sake.

gfwilliams commented 1 week ago

Thanks - do you have any examples of what this might be useful for?

As far as I can see from https://www.espruino.com/datasheets/CST816S.pdf there isn't really anything you can do. I know other devices have something but that's generally because there's stuff you can actually read/write

d3nd3 commented 1 week ago

https://wiki.pine64.org/index.php/PineTime#Touch_panel

I was going to play with some of these registers, especially: https://bitbucket.exodus-games.com/projects/KLIP/repos/knomi-creality/browse/lib/CST816S/CST816S.h?at=666ea26240c10829d3d971f8e6841f135c729fd8

I am wondering about the auto sleep feature eg. I just wanted to exhaust the options see what it can do.

d3nd3 commented 1 week ago

I was trying to write with this : I2C1.writeTo(0x15,0xE5,0x03)

But i'm not sure if it can work with the i2c api, or I have to use setup() function? can there be 2 i2c to the touch at once? I have no idea. That is why I reverted to this PR, kinda.

d3nd3 commented 1 week ago

This breaks PUCKJS on my repo , Actions Artifacts. Storage doesn't fit. Weird, it shouldn't affect puck ? Nvm I realise it was not most recent synched.

d3nd3 commented 1 week ago

My text editor was playing tricks on me, finally got a clean commit now.

d3nd3 commented 1 week ago

I spent many hours testing the : Bangle.touchWr(0xEE,100); - increasing the interupt frequency, even though interupts are not used.

It seems to reduce power, I recommend you test it yourself. Ofc it doens't give gains when touch controller is sleeping/off, but for all times when unlocked, it can give a substantial power saving.

I guess if you could start depending on interupts, and remove the polling code in espruino, or keep espruino polling and increase the interupt frequency. It is by default set to 1, which is 10ms, so 100 makes 1sec interval. That difference consumes less power. Probably on the order of 10-25%, by my rough estimates.(when unlocked)

gfwilliams commented 6 days ago

That's great - thanks! That PineTime link never really gave much helpful info for writing regs, but the other link looks really promising. I wonder what other more or less undocumented stuff is hiding.

I know folks have been asking about always on touchscreen but it never made sense because of the power draw.

Even if we had a low poll rate when the screen hadn't been touched for 60s and then raised it after, that could be really interesting.

even though interupts are not used.

Interrupts are definitely used for the touchscreen: https://github.com/espruino/Espruino/blob/master/libs/banglejs/jswrap_bangle.c#L3743-L3745

gfwilliams commented 6 days ago

Did you see this?

/*!
 *  @brief  Set Motion Mask
 *  @param  mask:
 *            bit2: EnConLR, Enable continuous scroll left/right
 *            bit1: EnConUD, Enable continuous scroll up/down
 *            bit0: EnDClick, Enable double click
 *  @return true if successful
 */
bool CST816S::setMotionMask(uint8_t mask) {
  return write_raw(CST816S_REG_MOTION_MASK, &mask, 1);
}

does that solve your double tap issue?

gfwilliams commented 6 days ago

How were you testing power draw?

I just did some tests - total power draw for the bangle quoted:

So I'm afraid it doesn't seem that this noticeably decreases power draw. But I guess there's hope for some other register to do something useful.

With a finger pressed and using scrolling it does seem to make a difference to power draw, but this is such a small percentage of time I don't think it's worth it (unless it's to make scrolling smoother)

d3nd3 commented 6 days ago

How were you testing power draw?

An unreliable method, of seeing the frequency when (analogRead(3)+analogRead(3)+analogRead(3)+analogRead(3))/4; doesn't decrease after a small time. It seemed robust though.

does that solve your double tap issue?

I will surely test this!

Your numbers seem a bit odd to me. 200/100/80/50? Ah, I see I mistyped 0xFA, I meant 0xEE.

Bangle.touchWr(0xEE,1); - default (100hz) Bangle.touchWr(0xEE,100); - 1hz

d3nd3 commented 6 days ago

Very ugly script, and i know it doesn't make much sense, and using different values in same script run is not needed for it to work. eg. fast = 0xEE[100] and slow = 0xEE[100] would also produce meaningful results. I compare against the GPS one, because its known how much mA it consumes. So thought I could estimate the others based on that.

/*
  script to compare side by side.
  compare first 0xEE:1 against 0xEE;1 -> 27%
  compare next 0xEE:1 against 0xEE:2 -> 30%
  compare next 0xEE:1 against 0xEE:100 -> 36%

  when touch controller is off : 0xE5:0x03 -> 51%
  gps is on : -> 1% [26mA]

  26/50 = 0.52mA

  26/36 = 0.72mA
  26/30 = 0.866mA
  26/27 = 0.9629mA

  I predict a 25% reduction in power usage when unlocked.
*/
let falseCount = 0;
let trueCount = 0;
setInterval(()=>{
  let fast;
  let slow;
  let tiny = ()=>new Promise((r)=>{
    setTimeout(()=>{
      r();
    },1);
  });
  let medium = ()=>new Promise((r)=>{
    setTimeout(()=>{
      r();
    },50);
  });

  //Bangle.setGPSPower(1);
  Bangle.touchWr(0xEE,1);
  tiny().then(()=>{
    fast = (analogRead(3)+analogRead(3)+analogRead(3)+analogRead(3))/4;
    return medium();
  }).then(()=>{
    //max 255 cos of api.
    //each unit is 10ms, 100=1sec, 1000=10sec, 10000=100sec
    Bangle.touchWr(0xEE,100);
    return tiny().then(()=>{
      slow = (analogRead(3)+analogRead(3)+analogRead(3)+analogRead(3))/4;
    });
  }).then(()=>{
    let ans = slow < fast;
    if (ans) trueCount+=1;
    else falseCount+=1;
    print(`slow < fast : ${slow < fast}\nTrues:${trueCount},Falses:${falseCount},Percentage:${(falseCount/trueCount).toFixed(2)}%`);
  });

},1000);
gfwilliams commented 6 days ago

I just tested here with a proper current meter between the Bangle and the battery.

Absolutely no effect writing to 0xEE I'm afraid (apart from a laggy touchscreen).

Also:

Bangle.touchWr(0xEE,0x100);

0x100 is hex 256, which doesn't fit in a byte and truncates down to writing 0.

d3nd3 commented 6 days ago

My bad I meant 100 :) But ye, if you say its no power difference, I guess I believe you, although does seem strange for me, considering my tests, are you sure you were UNLOCKED?

{
Bangle.setOptions({"lockTimeout":0});
Bangle.setLocked(false);

Bangle.on("drag",()=>{
  if (!Bangle.isBacklightOn())
    Bangle.setBacklight(1);
});

Bangle.on("touch",(b,info)=>{
  print(info.type);
  if (info.type == 1) {
    Bangle.showLauncher();
  }
});
}
gfwilliams commented 6 days ago

I tried 0,1,100 - with the following (when LCD backlight is off):

Bangle.setLCDTimeout(0)
Bangle.setLocked(0)

So that keeps the touchscreen on but not the backlight.

I'm confident to within at least 0.1mA there's no difference (at least when you're not touching the screen)

d3nd3 commented 6 days ago

I tried 0,1,100 - with the following (when LCD backlight is off):

Bangle.setLCDTimeout(0)
Bangle.setLocked(0)

So that keeps the touchscreen on but not the backlight.

I'm confident to within at least 0.1mA there's no difference (at least when you're not touching the screen)

Ok, so mb my power testing method there, is also affected by IRQ frequency, a bias.

gfwilliams commented 6 days ago

Well, if you're dragging over the screen to test then there probably is a difference, but as I said above that's not a big deal because you only spend a few seconds doing that a day. What I was testing was the idle power consumption (when there shouldn't be any IRQs)