Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More built-in code for ESP8266 #770

Closed
gfwilliams opened this issue Dec 22, 2015 · 77 comments
Closed

More built-in code for ESP8266 #770

gfwilliams opened this issue Dec 22, 2015 · 77 comments
Labels
ESP8266 This is only a problem on ESP8266 devices

Comments

@gfwilliams
Copy link
Member

Hi,

I just noticed that in the Makefile the ESP8266 only has USE_NET. I think at the least, USE_GRAPHICS might be handy for attaching graphics LCDs, and possibly USE_FILESYSTEM - which can allow you to connect an SD card to any available pins.

@tve I know you had concerns about the RAM usage, but I'd try it and see - this stuff is designed to statically allocate every little memory. I guess the only issue might the Flash usage?

@gfwilliams gfwilliams added the ESP8266 This is only a problem on ESP8266 devices label Dec 22, 2015
@MaBecker
Copy link
Contributor

MaBecker commented Jan 9, 2016

Hi,

added USE_GRAPHICS=1 and got a permanently reseting Espruino - any idea ?

r��S
ets Jan 8 2013,rst cause:4, boot mode:(3,6)
wdt reset
load 0x40100000, len 1396, room 16
tail 4
chksum 0x89
load 0x3ffe8000, len 776, room 4
tail 4
chksum 0xe8
load 0x3ffe8308, len 540, room 4
tail 8
chksum 0xc0
csum 0xc0
2nd boot version : 1.4(b1)
SPI Speed : 80MHz
SPI Mode : QIO
SPI Flash Size & Map: 32Mbit(512KB+512KB)
jump to run user1 @ 1000

@MaBecker
Copy link
Contributor

using this exports
export ESP8266_BOARD=1
export FLASH_4MB=1
export RELEASE=1
still rebooting but with a different cause

   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v84.MaBe_master_9aa07bc Copyright 2015 G.Williams
WARNING: the esp8266 port is in beta!
Flash map 4MB:512/512, manuf 0xe0 chip 0x4016
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)
load 0x40100000, len 1396, room 16
tail 4
chksum 0x89
load 0x3ffe8000, len 776, room 4
tail 4
chksum 0xe8
load 0x3ffe8308, len 540, room 4
tail 8
chksum 0xc0
csum 0xc0
2nd boot version : 1.4(b1)
  SPI Speed      : 80MHz
  SPI Mode       : QIO
  SPI Flash Size & Map: 32Mbit(512KB+512KB)
jump to run user1 @ 1000
r��

@MaBecker
Copy link
Contributor

first success full try with reduced vars (1000)

>process.memory();
={ "free": 971, "usage": 29, "total": 1000, "history": 0 }
>var g = Graphics.createArrayBuffer(16,8,24,{zigzag:true});
={
  "buffer": new ArrayBuffer(384)
 }
> 

@MaBecker
Copy link
Contributor

MaBecker commented Feb 1, 2016

got 1310 vars but very litte heap

>require("ESP8266").getState()
={
  "sdkVersion": "1.5.0",
  "cpuFrequency": 160, "freeHeap": 600, "maxCon": 10,
  "flashMap": "4MB:512/512",
  "flashKB": 4096,
  "flashChip": "0xe0 0x4016"
 }

any suggestion how to drop/shrink fonts ?

@gfwilliams
Copy link
Member Author

You could instead just modify their definition to fit into Flash memory instead?

@MaBecker
Copy link
Contributor

MaBecker commented Feb 1, 2016

not sure how too, any hint ?

now running with a compromise of 1000 vars

 _____                 _
|   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v84.MaBe_master_f35ac96 Copyright 2016 G.Williams
WARNING: the esp8266 port is in beta!
Flash map 4MB:512/512, manuf 0xe0 chip 0x4016
>require("ESP8266").getState()
={
  "sdkVersion": "1.5.0",
  "cpuFrequency": 160, "freeHeap": 9560, "maxCon": 10,
  "flashMap": "4MB:512/512",
  "flashKB": 4096,
  "flashChip": "0xe0 0x4016"
 }

@MaBecker
Copy link
Contributor

MaBecker commented Feb 1, 2016

that is the reason why I am so keen on having GRAPHIC

i2c-0-91-128x32-white-oled-lcd-display

@gfwilliams
Copy link
Member Author

Looks like you need something a bit like this: https://github.com/espruino/Espruino/blob/master/src/jsutils.h#L62

Ideally you'd make a new #define in jsutils.h that just applied __attribute__((section(".irom.literal"))) for ESP8266 and did nothing for other platforms, then you'd make sure you use the READ_FLASH_UINT8 macro whenever you were reading from the font.

@MaBecker
Copy link
Contributor

MaBecker commented Feb 1, 2016

ok, extended jsutil.h see below

can you please name a file and line where and how to use READ_FLASH_UINT8 and how to upload the fonts.

#if defined(ESP8266)
// For the esp8266 we need to add CALLED_FROM_INTERRUPT to all functions that may execute at
// interrupt time so they get loaded into static RAM instead of flash. We define
// it as a no-op for everyone else. This is identical the ICACHE_RAM_ATTR used elsewhere.
#define CALLED_FROM_INTERRUPT __attribute__((section(".iram1.text")))

//-- MaBecker - Begin ---------------------
/** Place constant strings into flash when we can in order to save RAM space. Strings in flash
    must be accessed with word reads on aligned boundaries, so we'll have to copy them before
    regular use. */
#define FLASH_STR(name, x) static char name[] __attribute__((section(".irom.literal"))) __attribute__((aligned(4))) = x

/// Get the length of a string in flash
size_t flash_strlen(const char *str);

/// Copy a string from flash to RAM
char *flash_strncpy(char *dest, const char *source, size_t cap);

/** Read a uint8_t from this pointer, which could be in RAM or Flash.
    On ESP8266 you have to read flash in 32 bit chunks, so force a 32 bit read
    and extract just the 8 bits we want */
#define READ_FLASH_UINT8(ptr) ({ uint32_t __p = (uint32_t)(char*)(ptr); volatile uint32_t __d = *(uint32_t*)(__p & (uint32_t)~3); ((uint8_t*)&__d)[__p & 3]; })
//-- MaBecker - End -----------------------

#else
#define CALLED_FROM_INTERRUPT
#endif

@gfwilliams
Copy link
Member Author

Not quite sure I understand what you've done there - isn't that pretty much what's in jsutils already?

I meant, something like:

#ifdef ESP8266
#define IN_FLASH_MEMORY __attribute__((section(".irom.literal")))
#else
#define IN_FLASH_MEMORY
#endif
#define READ_FLASH_UINT16(ptr) ((READ_FLASH_UINT8(ptr)<<8) | READ_FLASH_UINT8(ptr+1) )

Look in https://github.com/espruino/Espruino/tree/master/libs/graphics for fonts. For example:

https://github.com/espruino/Espruino/blob/master/libs/graphics/bitmap_font_3x5.c

const unsigned short LCD_FONT_3X5[LCD_FONT_3X5_CHARS*5] IN_FLASH_MEMORY = {
// ...
void graphicsDrawChar4x6(JsGraphics *gfx, short x1, short y1, char ch) {
  int idx = ((unsigned char)ch) - 33;
  if (idx<0 || idx>=LCD_FONT_3X5_CHARS) return; // no char for this - just return
  int cidx = idx % 5;
  idx -= cidx;
  int y;
  for (y=0;y<6;y++) {
    unsigned short line = READ_FLASH_UINT16[&LCD_FONT_3X5[idx + y]] >> (cidx*3);
    if (line&1) graphicsSetPixel(gfx, x1+0, y+y1, gfx->data.fgColor);
    if (line&2) graphicsSetPixel(gfx, x1+1, y+y1, gfx->data.fgColor);
    if (line&4) graphicsSetPixel(gfx, x1+2, y+y1, gfx->data.fgColor);
  }
}

for rendering of the vector font you have to look into graphics.c though

@MaBecker
Copy link
Contributor

MaBecker commented Feb 2, 2016

sorry, just starting with stuff like this, hope to improve day by day - thanks

like to check result with find_big_ram.sh and find_big_rom.sh
how to create the input put file named espruino_XXXX.lst for this tools ?

make topstrings is broken on MAC OS X, will fixit and make a new section for .irom.literal

@MaBecker
Copy link
Contributor

MaBecker commented Feb 2, 2016

changed code in jsutils.h and bitmap_font_4x6

DISABLE_LTO=1 make

used xtensa-lx106-elf-objdump -s ./libs/graphics/bitmap_font_4x6.oto create this text files

version_rodata.txt

version_irom_literal.txt

@gfwilliams Why is the contents of section .rodata or .irom.literal using so much space filled with 0x00 ?

@gfwilliams
Copy link
Member Author

I have no idea - it could be zero-initialised structures? I'd have hoped that GCC would be smart enough to group them together in RAM and zero-init them with a loop, but I don't remember seeing it do that in ARM and I doubt it does for Xtensa.

@MaBecker
Copy link
Contributor

MaBecker commented Feb 3, 2016

v1: const unsigned short LCD_FONT_4X6[LCD_FONT_4X6_CHARS*6] IN_FLASH_MEMORY = { ...}

v2: const unsigned short LCD_FONT_4X6[] IN_FLASH_MEMORY = { ...}

result: v2 shrinks irom.literal ;-)

bitmap_font_4x6.o.irom.literal_v1.txt

bitmap_font_4x6.o.irom.literal_v2.txt

@gfwilliams
Copy link
Member Author

Wow, thanks! So I was basically allocating 5x more memory than needed! I guess all those fonts could be fixed in a similar way.

@MaBecker
Copy link
Contributor

MaBecker commented Feb 3, 2016

this is what the latest Makefile from espruion/ESPRUINO uses for GRAPHICS:

ifdef USE_GRAPHICS
DEFINES += -DUSE_GRAPHICS
INCLUDE += -I$(ROOT)/libs/graphics
WRAPPERSOURCES += libs/graphics/jswrap_graphics.c
SOURCES += \
libs/graphics/bitmap_font_4x6.c \
libs/graphics/graphics.c \
libs/graphics/lcd_arraybuffer.c \
libs/graphics/lcd_js.c

changed 4x6 to 3x5 and started make

holy moly const unsigned short LCD_FONT_3X5 this full off syntax errors - fixed and yes same result !

pull request: #804

@MaBecker
Copy link
Contributor

MaBecker commented Feb 3, 2016

  • default bitmap_font_4x6 is now stored on flash memory

will now start some test

@MaBecker
Copy link
Contributor

MaBecker commented Feb 3, 2016

decided to test ram font first, but didn't look right ?!

bitmap_font_3x5.c

const unsigned short LCD_FONT_3X5[] IN_FLASH_MEMORY = { // from 33 up to 127
    PACK_5_TO_16( _X_ , X_X , _X_ , _X_ , X_X ), // !"#$%

and bitmap_font_4x6.c

const unsigned short LCD_FONT_4X6[]  = { // from 33 up to 127
    PACK_5_TO_16( _X_ , X_X , X_X , _X_ , X_X ),

are setup with the same entries.

Gordon, please double check.

@MaBecker
Copy link
Contributor

MaBecker commented Feb 4, 2016

tried vector font, result looks strange

// connected to a 8x8 neopixel plate on pin D5
var esp = require('ESP8266');
var pin = D5;

var leds = Graphics.createArrayBuffer(8,8,24,{zigzag:true}); 
leds.flip = function() { esp.neopixelWrite(pin,leds.buffer); };

leds.clear();
leds.setFontVector(5);
leds.setColor(0.2,0,0);
leds.drawString("!",0,0);
leds.flip();

img_4539

Any idea ?

@MaBecker
Copy link
Contributor

MaBecker commented Feb 4, 2016

found it, something wrong with the initial setting of zigzag - no idea where to change that

var leds = Graphics.createArrayBuffer(8,8,24,{zigzag:false});
leds.flip = function() { esp.neopixelWrite(pin,leds.buffer); };

leds.clear();
leds.setFontVector(5);
leds.setColor(0.2,0,0);
leds.drawString("!",0,0);
leds.flip(); 

img_4540

@gfwilliams
Copy link
Member Author

something wrong with the initial setting of zigzag

I'm not sure what you mean? zigzag is for displays with the pixels wired in a zig-zag pattern - like the RGB123. The effect you're showing is what you'd expect if you wired it to a display that wasn't zig-zagged.

bitmap_font_3x5.c and bitmap_font_4x6.c are setup with the same entries.

I don't think so? One is 6px deep, the other is 5px deep. Both are 3px wide (excluding the space between chars) which is a bit confusing though.

@MaBecker
Copy link
Contributor

MaBecker commented Feb 4, 2016

so font 4x6 : 3x5 in 4x6 - got that

my neopixel plate is zigzag wired like this

00 01 02 03 04 05 06 07
09 10 11 12 13 14 15 16
......

to address the pixel correctly I have to set zigzag option to false, what is in my understanding wrong compared with the docs.

@gfwilliams
Copy link
Member Author

so font 4x6 : 3x5 in 4x6 - got that

If you look, you'll see that the 4x6 font does use the bottom row occasionally, so it isn't just a 3x5 font with the bottom row left empty.

00 01 02 03 04 05 06 07
09 10 11 12 13 14 15 16

Yes, that's an entirely normal scanline-style layout. How would you lay out a grid of pixels like that in a way that was less zig-zaggy??

zigzag is for:

00 01 02 03 04 05 06 07
15 14 13 12 11 10 09 08
...

@gfwilliams
Copy link
Member Author

Also, the docs say zigzag = whether to alternate the direction of scanlines for rows - I think that makes sense in this case?

@MaBecker
Copy link
Contributor

MaBecker commented Feb 4, 2016

thanks for enlighten me !

@MaBecker
Copy link
Contributor

MaBecker commented Feb 8, 2016

using font stored in irom will reboot if using drawSting()

downloaded yesterdays source version

found macro READ_FLASH_UINT8 in src/jsutils.h, added

#ifdef ESP8266
#define IN_FLASH_MEMORY __attribute__((section(".irom.literal")))
#else
#define IN_FLASH_MEMORY
#endif

tried to use it like this in file lib/graphics/bitmap_font_4x6.c

//const unsigned short LCD_FONT_4X6[]  = { // from 33 up to 127
const unsigned short LCD_FONT_4X6[] IN_FLASH_MEMORY = { // from 33 up to 127
......
    //int line = LCD_FONT_4X6[idx + y] >> (cidx*3);
    int line = READ_FLASH_UINT8(LCD_FONT_4X6[idx + y]) >> (cidx*3);

ESP still reboots, what am I missing ....

@gfwilliams I need some help on this

@gfwilliams
Copy link
Member Author

Why didn't you use the code I posted above? LCD_FONT_4X6 is 16 bits, so you'd need to make and use a READ_FLASH_UINT16.

I don't know whether that would help, but it would be a good start.

edit: it's got a typo with the [ brackets.

Other thing you could try is commenting out the function altogether. It could be the problem is elsewhere.

@MaBecker
Copy link
Contributor

MaBecker commented Feb 8, 2016

rewriting the changes correctly and TaTa, no more dump

bitmap_font_4x6.c

const unsigned short LCD_FONT_4X6[] IN_FLASH_MEMORY = {
....
unsigned short line = READ_FLASH_UINT16(&LCD_FONT_4X6[idx + y]) >> (cidx*4);

jsutils.h

#if defined(ESP8266)
.....
#define IN_FLASH_MEMORY __attribute__((section(".irom.literal")))
#define READ_FLASH_UINT8(ptr) ({ uint32_t __p = (uint32_t)(char*)(ptr); volatile uint32_t __d = *(uint32_t*)(__p & (uint32_t)~3); ((uint8_t*)&__d)[__p & 3]; })
....
#else
....
#define IN_FLASH_MEMORY
#define READ_FLASH_UINT8(ptr) (*(uint8_t*)(ptr))
....
#endif

#define READ_FLASH_UINT16(ptr) ((READ_FLASH_UINT8(ptr)<<8) | READ_FLASH_UINT8(ptr+1) )

checking the result will bing up a new thing:

leds.drawString("X",0,1);

is showing this:

fullsizerender

    PACK_5_TO_16( X_X , X_X , XXX , XXX , X__ ),
    PACK_5_TO_16( X_X , X_X , __X , X__ , X__ ),
    PACK_5_TO_16( _X_ , XXX , _X_ , X__ , _X_ ),
    PACK_5_TO_16( X_X , _X_ , X__ , X__ , __X ),
    PACK_5_TO_16( X_X , _X_ , XXX , XXX , __X ),
    PACK_5_TO_16( ___ , ___ , ___ , ___ , ___ ),

    PACK_5_TO_16( XXX , _X_ , ___ , X__ , ___ ),

@gfwilliams any idea ?

@MaBecker
Copy link
Contributor

next test: print first six chars to console and compare with peek16()

// [offset] = <value of PACK_5_16>, <peek16(addr+offset);
>first_six_chars();
[0]=556a,556a
[1]=556a,ea55
[2]=1fea,1fea
[3]=2d42,421f
[4]=47c0,2d42
[5]=5f42,c02d
[6]=400,47c0
[7]=2496,4247
[8]=7316,5f42
[9]=5303,5f
[a]=306,400
[b]=487,9604

@MaBecker
Copy link
Contributor

@gfwilliams | @tve need some new ideas to get this right

@MaBecker
Copy link
Contributor

with all the optimization of const strings coming with the standard code in 1v85 it is possible to have 1200 vars and 5200 heap.

DISABLE_LTO=1 USE_GRAPHICS=1 make

>require("ESP8266").getState();
={
  "sdkVersion": "1.5.0",
  "cpuFrequency": 160, "freeHeap": 5200, "maxCon": 10,
  "flashMap": "4MB:512/512",
  "flashKB": 4096,
  "flashChip": "0xe0 0x4016"
 }
>process.memory();
={ "free": 1163, "usage": 37, "total": 1200, "history": 14 }
> 
Graphics.prototype.print = function() { 
  for (var y=0;y<this.getHeight();y++)
    console.log(new Uint8Array(this.buffer,this.getWidth()*y,this.getWidth()));
};

var g = Graphics.createArrayBuffer(8,8,8);
g.setColor(1);
g.drawString("X",0,0);
g.print();

/*
console output:
new Uint8Array([1, 0, 1, 0, 0, 0, 0, 0])
new Uint8Array([1, 0, 1, 0, 0, 0, 0, 0])
new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0])
new Uint8Array([1, 0, 1, 0, 0, 0, 0, 0])
new Uint8Array([1, 0, 1, 0, 0, 0, 0, 0])
new Uint8Array(8)
new Uint8Array(8)
new Uint8Array(8)
*/

@MaBecker
Copy link
Contributor

.

@wilberforce
Copy link
Member

@MaBecker

Does the heap size just end up with whatever ram is left, or is there a setting for this?

@MaBecker
Copy link
Contributor

@wilberforce there is no setting for heap.

this is my understanding of how heap is influenced:

  • increase vars and/or load more modules will decrease heap
  • moving const strings and arrays to flash (".irom.literal") will increase heap

@tve
Copy link
Contributor

tve commented Mar 16, 2016

heap size is what's left

@wilberforce
Copy link
Member

How much heap is required? I understand this is application dependent. We start with 80K and I think we loose 1/2 to the interpreter - I'm wondering how the jsVars and heap available compare to ARM implementations

@MaBecker
Copy link
Contributor

try to write own lib to understand how .irom.literal stores data.

printf is not working they way I use it, any hints ?

extern int os_printf_plus(const char *format, ...)  __attribute__((format(printf, 1, 2)));
#define printf os_printf_plus

#include "jswrap_mabe.h" 
#include "jsinteractive.h" 

#define ESP_READ_FLASH_UINT8(ptr) ({ uint32_t __p = (uint32_t)(char*)(ptr); if (__p < 0x400000) __p|=0x40200000; volatile uint32_t __d = *(uint32_t*)(__p & (uint32_t)~3); ((uint8_t*)&__d)[__p & 3]; })
#define ESP_READ_FLASH_UINT16(ptr) ((ESP_READ_FLASH_UINT8(ptr)<<8) | ESP_READ_FLASH_UINT8(ptr+1) )    
//#define ESP_READ_FLASH_UINT16(ptr) ((ESP_READ_FLASH_UINT8(ptr+1)<<8) | ESP_READ_FLASH_UINT8(ptr) ) 
#define IN_FLASH_MEMORY   __attribute__ ((section(".irom.literal"))) //__attribute__((aligned(4))) 

unsigned short MYARRAY1[] = { 65,66,67,68,69,70,71,72 };
const unsigned short MYARRAY2[] = { 73,74,75,76,77,78,79,80 };
unsigned short MYARRAY3[] IN_FLASH_MEMORY = { 81,82,83,84,85,86,87,88 };

/*JSON{
  "type" : "class",
  "class" : "Mabe"
}*/

/*JSON{
  "type" : "staticmethod",
  "class" : "Mabe",
  "name" : "test01",
  "generate" : "jswrap_mabe_test01"
}*/

void jswrap_mabe_test01() {

    jsiConsolePrint("Hello MaBe!\r\n");

    printf("MYARRAY1: %u,%u\n",MYARRAY1[0],MYARRAY1[1]);
    printf("MYARRAY2: %u,%u\n",MYARRAY2[0],MYARRAY2[1]);

    printf("MYARRAY3: %u,%u\n",
        ESP_READ_FLASH_UINT16(&MYARRAY3[0]),
        ESP_READ_FLASH_UINT16(&MYARRAY3[1])
    );
}
/*
output
>Mabe.test01();
Hello MaBe!
=undefined
> 

xtensa-lx106-elf-objdump  -s libs/mabe/jswrap_mabe.o

Contents of section .data:
 0000 41004200 43004400 45004600 47004800  A.B.C.D.E.F.G.H.
Contents of section .rodata.str1.1:
 0000 4d594152 52415931 3a202575 2c25750a  MYARRAY1: %u,%u.
 0010 004d5941 52524159 323a2025 752c2575  .MYARRAY2: %u,%u
 0020 0a004d59 41525241 59333a20 25752c25  ..MYARRAY3: %u,%
 0030 750a00                               u..             
Contents of section .irom.literal:
 0000 48656c6c 6f204d61 4265210d 0a005100  Hello MaBe!...Q.
 0010 52005300 54005500 56005700 5800      R.S.T.U.V.W.X.  
Contents of section .rodata:
 0000 49004a00 4b004c00 4d004e00 4f005000  I.J.K.L.M.N.O.P.

*/

@MaBecker
Copy link
Contributor

using jsiConsolePrintf() with %d and ESP_READ_FLASH_UINT8 works

    jsiConsolePrintf("MYARRAY1: %d,%d\r\n",MYARRAY1[0],MYARRAY1[1]);
    jsiConsolePrintf("MYARRAY2: %d,%d\n",MYARRAY2[0],MYARRAY2[1]);

    jsiConsolePrintf("MYARRAY3: %d,%d\n",
        ESP_READ_FLASH_UINT8(&MYARRAY3[0]),
        ESP_READ_FLASH_UINT8(&MYARRAY3[1])
    );

/*
>Mabe.test01();
Hello MaBe!
MYARRAY1: 65,66
MYARRAY2: 73,74
MYARRAY3: 81,82
=undefined
> 
*/

@tve
Copy link
Contributor

tve commented Mar 17, 2016

How much heap is required?

YMMV :-)
I don't have much luck with 4KB or less. 5KB seems "OK" with a single outgoing mqtt connection and an incoming telnet connection. But you better try for yourself and include tests where the connection is slow/bad causing packet retransmissions. I still see the SDK allocating >2KB buffers at times, so if there's less free heap than that you're effectively toast.

@MaBecker
Copy link
Contributor

including some lines of the LCD_FONT_3X6 array reading and print them with ESP_READ_FLASH_UINT8 and ESP_READ_FLASH_UINT16 explains whats going wrong

ESP_READ_FLASH_UINT16 is not working as expected

LCD_FONT_4X6_1_8: 6a,ea,42,c0,42,00,57,58
LCD_FONT_4X6_1_16: 6aea,ea42,42c0,c042,4200,0051,0057,0058

@gfwilliams can you please suggest a new version of ESP_READ_FLASH_UINT16 that can handle this ?

@MaBecker
Copy link
Contributor

Contents of section .irom.literal:
 0000 4c43445f 464f4e54 5f345836 5f315f31  LCD_FONT_4X6_1_1
 0010 363a2025 3034782c 25303478 2c253034  6: %04x,%04x,%04
 0020 782c2530 34782c25 3034782c 25303478  x,%04x,%04x,%04x
 0030 2c253034 782c2530 34780a00 4c43445f  ,%04x,%04x..LCD_
 0040 464f4e54 5f345836 5f315f38 3a202530  FONT_4X6_1_8: %0
 0050 32782c25 3032782c 25303278 2c253032  2x,%02x,%02x,%02
 0060 782c2530 32782c25 3032782c 25303278  x,%02x,%02x,%02x
 0070 2c253032 780a0000 4d594152 52415933  ,%02x...MYARRAY3
 0080 3a202564 2c25642c 25642c25 642c2564  : %d,%d,%d,%d,%d
 0090 2c25642c 25642c25 640a0000 4d594152  ,%d,%d,%d...MYAR
 00a0 52415932 3a202564 2c25642c 25642c25  RAY2: %d,%d,%d,%
 00b0 640d0a00 4d594152 52415931 3a202564  d...MYARRAY1: %d
 00c0 2c25642c 25642c25 640d0a00 48656c6c  ,%d,%d,%d...Hell

 00d0 6f204d61 4265210d 0a006a55 ea1f422d  o MaBe!...jU..B-
 00e0 c047425f 00045100 52005300 54005500  .GB_..Q.R.S.T.U.

 00f0 56005700 5800                        V.W.X.          

@gfwilliams
Copy link
Member Author

I'm not sure I really understand what's going on? Please can you post up the code you used to print:

LCD_FONT_4X6_1_8: 6a,ea,42,c0,42,00,57,58
LCD_FONT_4X6_1_16: 6aea,ea42,42c0,c042,4200,0051,0057,0058

The first 5 or so entries of LCD_FONT_4X6_1_16 seem to be doing what I'd expect, but something odd happens after that

@MaBecker
Copy link
Contributor

    jsiConsolePrintf("LCD_FONT_4X6_1_8: %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
        ESP_READ_FLASH_UINT8(&LCD_FONT_4X6_1[0]),
        ESP_READ_FLASH_UINT8(&LCD_FONT_4X6_1[1]),
        ESP_READ_FLASH_UINT8(&LCD_FONT_4X6_1[2]),
        ESP_READ_FLASH_UINT8(&LCD_FONT_4X6_1[3]),
        ESP_READ_FLASH_UINT8(&LCD_FONT_4X6_1[4]),
        ESP_READ_FLASH_UINT8(&LCD_FONT_4X6_1[5])
    );
    jsiConsolePrintf("LCD_FONT_4X6_1_16: %04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x\n",
        ESP_READ_FLASH_UINT16(&LCD_FONT_4X6_1[0]),
        ESP_READ_FLASH_UINT16(&LCD_FONT_4X6_1[1]),
        ESP_READ_FLASH_UINT16(&LCD_FONT_4X6_1[2]),
        ESP_READ_FLASH_UINT16(&LCD_FONT_4X6_1[3]),
        ESP_READ_FLASH_UINT16(&LCD_FONT_4X6_1[4]),
        ESP_READ_FLASH_UINT16(&LCD_FONT_4X6_1[5])
    );

@gfwilliams
Copy link
Member Author

That's working fine as far as I can tell. Note: you've got 8 ,%04x but only 6 arguments, so the final 2 will be wrong.

How is LCD_FONT_4X6_1 defined? As a char array, or a short array?

In the original file it's const unsigned short LCD_FONT_4X6, and yes - if you're getting those kind of results with that then something is wrong - but I'd be struggling to see how that could happen!

@MaBecker
Copy link
Contributor

definition:

const unsigned short LCD_FONT_4X6_0[] = { // from 33 up to 127
    PACK_5_TO_16( _X_ , X_X , X_X , _X_ , X_X ),
    PACK_5_TO_16( _X_ , X_X , XXX , XXX , __X ),
    PACK_5_TO_16( _X_ , ___ , X_X , XX_ , _X_ ),
    PACK_5_TO_16( ___ , ___ , XXX , _XX , X__ ),
    PACK_5_TO_16( _X_ , ___ , X_X , XXX , X_X ),
    PACK_5_TO_16( ___ , ___ , ___ , _X_ , ___ )
};

unsigned short LCD_FONT_4X6_1[] IN_FLASH_MEMORY = { // from 33 up to 127
    PACK_5_TO_16( _X_ , X_X , X_X , _X_ , X_X ),
    PACK_5_TO_16( _X_ , X_X , XXX , XXX , __X ),
    PACK_5_TO_16( _X_ , ___ , X_X , XX_ , _X_ ),
    PACK_5_TO_16( ___ , ___ , XXX , _XX , X__ ),
    PACK_5_TO_16( _X_ , ___ , X_X , XXX , X_X ),
    PACK_5_TO_16( ___ , ___ , ___ , _X_ , ___ )
};

ok as fare as i understand the type cast (char*) causes this issue, values are stored as 2 byte values , see contents of section .irom.literal

this reads the low byte

  #define ESP_READ_FLASH_UINT8(ptr) ({ uint32_t __p = (uint32_t)(char*)(ptr) ........

this reads two times low byte of prt and ptr+1

  #define ESP_READ_FLASH_UINT16(ptr) ((ESP_READ_FLASH_UINT8(ptr)<<8) | ESP_READ_FLASH_UINT8(ptr+1) )    

I guess this would help: change to read high and low byte of same ptr

#define ESP_READ_FLASH_UINT16(ptr) ({ uint32_t __p = (uint32_t)(unsigned short*)(ptr) .......

but I don't know how to change the rest of the line to return eg 0x6a55

@gfwilliams
Copy link
Member Author

Ahh, try:

  #define ESP_READ_FLASH_UINT16(ptr) ((ESP_READ_FLASH_UINT8(ptr)<<8) | ESP_READ_FLASH_UINT8(((char*)ptr)+1) )  

The issue is that the pointer is to a 16 bit value, so adding 1 to it jumps 16 bits forward, not 8 as was intended.

You might also need to try:

  #define ESP_READ_FLASH_UINT16(ptr) (ESP_READ_FLASH_UINT8(ptr) | (ESP_READ_FLASH_UINT8(((char*)ptr)+1)<<8) )  

Which would reverse the order of the 2 bytes (if they turned out to be wrong)

@MaBecker
Copy link
Contributor

Yep, now all chars are correct !

Used this statements:

#define ESP_READ_FLASH_UINT8(ptr) ({ uint32_t __p = (uint32_t)(char*)(ptr); if (__p < 0x400000) __p|=0x40200000; volatile uint32_t __d = *(uint32_t*)(__p & (uint32_t)~3); ((uint8_t*)&__d)[__p & 3]; })
#define ESP_READ_FLASH_UINT16(ptr) (ESP_READ_FLASH_UINT8(ptr) | (ESP_READ_FLASH_UINT8(((char*)ptr)+1)<<8) )  

#define IN_FLASH_MEMORY   __attribute__ ((section(".irom.literal"))) //__attribute__((aligned(4))) 
......
//int line = LCD_FONT_4X6[idx + y] >> (cidx*3)
unsigned short line = ESP_READ_FLASH_UINT16(&LCD_FONT_4X6[idx + y]) >> (cidx*3);

Next is to move this defines to jsutils.h and than continue with vector font

@MaBecker
Copy link
Contributor

jsutil.h

#if defined(ESP8266)
#define IN_FLASH_MEMORY   __attribute__ ((section(".irom.literal"))) //__attribute__((aligned(4))) 
#else
#define IN_FLASH_MEMORY 
#endif
#define READ_FLASH_UINT16(ptr) (READ_FLASH_UINT8(ptr) | (READ_FLASH_UINT8(((char*)ptr)+1)<<8) )  

bitmap_font_4x6.c

unsigned short LCD_FONT_4X6[] IN_FLASH_MEMORY = {
....
unsigned short line = READ_FLASH_UINT16(&LCD_FONT_4X6[idx + y]) >> (cidx*3);

@wilberforce
Copy link
Member

I was going to suggest that you dropped the ESP_ prefix so this is platform agnostic - looks like you have done already!

As far as the naming goes I'm wondering if there is a naming convention we can use that it will still read ok for non-rom builds.
What I mean is READ_FLASH doesn't apply in the normal case, but the wording implies it does!

@MaBecker
Copy link
Contributor

vector_font.h

unsigned char vectorFontPolys[] IN_FLASH_MEMORY = {

graphics.c

....
verts[idx+0] = (short)(x1+(((READ_FLASH_UINT8(&vectorFontPolys[vertOffset+i+0])&0x7F)*size+(VECTOR_FONT_POLY_SIZE/2))/VECTOR_FONT_POLY_SIZE));
    verts[idx+1] = (short)(y1+(((READ_FLASH_UINT8(&vectorFontPolys[vertOffset+i+1])&0x7F)*size+(VECTOR_FONT_POLY_SIZE/2))/VECTOR_FONT_POLY_SIZE));
....
    if (READ_FLASH_UINT8(&vectorFontPolys[vertOffset+i+1]) & VECTOR_FONT_POLY_SEPARATOR) {

test vector font

Graphics.prototype.print = function() { 
  for (var y=0;y<this.getHeight();y++)
    console.log(new Uint8Array(this.buffer,this.getWidth()*y,this.getWidth()));
};

var g = Graphics.createArrayBuffer(16,16,8);
g.setColor(1);
g.setFontVector(16);
g.drawString("A",0,0);
g.print();
g.clear();

/*
new Uint8Array(16)
new Uint8Array([0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0])
new Uint8Array([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0])
new Uint8Array([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0])
new Uint8Array([0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0])
new Uint8Array([0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0])
new Uint8Array([0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0])
new Uint8Array([0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0])
new Uint8Array([0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0])
new Uint8Array([0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0])
new Uint8Array([0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0])
new Uint8Array([0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0])
new Uint8Array([0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0])
new Uint8Array([0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0])
new Uint8Array([1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0])
new Uint8Array([1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0])
*/

after reset

>process.memory();
={ "free": 1373, "usage": 27, "total": 1400, "history": 0 }
>require("ESP8266").getState()
={
  "sdkVersion": "1.5.0",
  "cpuFrequency": 160, "freeHeap": 7376, "maxCon": 10,
  "flashMap": "4MB:512/512",
  "flashKB": 4096,
  "flashChip": "0xe0 0x4016"
 }

@gfwilliams do you see any thing else that can be moved to flash in GRAPHICS ?

@MaBecker
Copy link
Contributor

xtensa-lx106-elf-objdump list for all object files in libs/graphics

od_libs_graphics.txt

@gfwilliams
Copy link
Member Author

Looks great!

@MaBecker Nothing comes to mind... Do you think you could issue a pull request for this?

@MaBecker
Copy link
Contributor

sure !

@MaBecker
Copy link
Contributor

created pull request 820 - 823

@MaBecker
Copy link
Contributor

MaBecker commented Apr 5, 2016

@gfwilliams I suggest to close this issue and open a new issue for USE_FILESYSTEM because I have no SSD drive to test this and work on USE_GRAPHICS is completed and as standard build for ESP in Makefile.

What do you think ?

@gfwilliams
Copy link
Member Author

Yeah - to be honest I think I'll just close this. I'm not sure many people will use filesystem now there is the built-in Flash library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ESP8266 This is only a problem on ESP8266 devices
Projects
None yet
Development

No branches or pull requests

5 participants