Add: async partial flush
This commit is contained in:
		| @@ -9,7 +9,12 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type Display interface { | type Display interface { | ||||||
| 	Flush(img *image.Gray) error | 	Flush(crystal, page byte) | ||||||
|  |  | ||||||
|  | 	// Image functions | ||||||
|  | 	GetImg() *image.Gray | ||||||
|  | 	LockImg() | ||||||
|  | 	UnlockImg() | ||||||
| 	GetBounds() image.Rectangle | 	GetBounds() image.Rectangle | ||||||
|  |  | ||||||
| 	Test(ctx context.Context) error | 	Test(ctx context.Context) error | ||||||
|   | |||||||
| @@ -6,18 +6,35 @@ import ( | |||||||
| 	"image" | 	"image" | ||||||
| 	"log" | 	"log" | ||||||
| 	"math/rand" | 	"math/rand" | ||||||
|  | 	"sync" | ||||||
|  | 	"sync/atomic" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"gitea.unprism.ru/yotia/display-test/pkg/mt12232a" | 	"gitea.unprism.ru/yotia/display-test/pkg/mt12232a" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var _ = rand.Int() // TMP for import to exist | var _ = rand.Int() // for import existance | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	mt12232aW    = 122 | ||||||
|  | 	mt12232aH    = 32 | ||||||
|  | 	flushChanCap = 24 // Flush channel capacity | ||||||
|  | ) | ||||||
|  |  | ||||||
| type displayMt12232a struct { | type displayMt12232a struct { | ||||||
| 	logger *log.Logger | 	logger *log.Logger | ||||||
|  |  | ||||||
|  | 	// Image | ||||||
|  | 	img      *image.Gray | ||||||
|  | 	imgMutex sync.Mutex | ||||||
|  |  | ||||||
| 	// GPIO pins | 	// GPIO pins | ||||||
| 	dev mt12232a.Device | 	dev mt12232a.Device | ||||||
|  |  | ||||||
|  | 	// Flush goroutine | ||||||
|  | 	flushCancel     context.CancelFunc | ||||||
|  | 	pagesFlushFlags atomic.Uint32 // (!use only 8 bits) Every bit corresponds to page/crystal with this number | ||||||
|  | 	flushDone       chan struct{} | ||||||
| } | } | ||||||
|  |  | ||||||
| func newMt12232a(logger *log.Logger) (Display, error) { | func newMt12232a(logger *log.Logger) (Display, error) { | ||||||
| @@ -31,15 +48,16 @@ func newMt12232a(logger *log.Logger) (Display, error) { | |||||||
| 		bits[i] = make([]byte, 122) | 		bits[i] = make([]byte, 122) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// if err := dev.PowerOn(); err != nil { | 	ctx, cancel := context.WithCancel(context.Background()) | ||||||
| 	// 	return nil, fmt.Errorf("power on: %w", err) |  | ||||||
| 	// } |  | ||||||
|  |  | ||||||
| 	// Setup submit goroutine | 	// Setup submit goroutine | ||||||
| 	d := displayMt12232a{ | 	d := displayMt12232a{ | ||||||
| 		logger:      logger, | 		logger:      logger, | ||||||
| 		dev:         dev, | 		dev:         dev, | ||||||
|  | 		flushCancel: cancel, | ||||||
|  | 		img:         image.NewGray(image.Rect(0, 0, mt12232aW, mt12232aH)), | ||||||
|  | 		flushDone:   make(chan struct{}), // For waiting flush to finish before exiting | ||||||
| 	} | 	} | ||||||
|  | 	go d.flushLoop(ctx) | ||||||
|  |  | ||||||
| 	// Temp debug draw | 	// Temp debug draw | ||||||
| 	//if st0, st1 := d.dev.ReadStatus(0), d.dev.ReadStatus(1); false { //st0&0x20 == 0 && st1&0x20 == 0 { | 	//if st0, st1 := d.dev.ReadStatus(0), d.dev.ReadStatus(1); false { //st0&0x20 == 0 && st1&0x20 == 0 { | ||||||
| @@ -131,66 +149,23 @@ func (d *displayMt12232a) powerOn() error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (d *displayMt12232a) Test(ctx context.Context) error { | func (d *displayMt12232a) Test(ctx context.Context) error { | ||||||
| 	d.dev.WriteCode(0, 0xB8) |  | ||||||
| 	d.dev.WriteCode(0, 0x14) |  | ||||||
| 	d.dev.WriteData(0, 0xAE) |  | ||||||
| 	start := time.Now() | 	start := time.Now() | ||||||
|  |  | ||||||
| 	d.status("4") |  | ||||||
| 	for p := 0; p < 4; p++ { | 	for p := 0; p < 4; p++ { | ||||||
| 		// First |  | ||||||
|  |  | ||||||
| 		// d.dev.WriteCode(0, byte(p)|0xB8) |  | ||||||
| 		// d.dev.WriteCode(0, 0x13) |  | ||||||
| 		// for c := 0; c < 61; c++ { |  | ||||||
| 		// d.dev.WriteData(0, 0) |  | ||||||
| 		// } |  | ||||||
| 		// d.dev.WriteCode(1, byte(p)|0xB8) |  | ||||||
| 		// d.dev.WriteCode(1, 0x00) |  | ||||||
| 		// for c := 0; c < 61; c++ { |  | ||||||
| 		// d.dev.WriteData(1, 0) |  | ||||||
| 		// } |  | ||||||
| 		// |  | ||||||
| 		// Second |  | ||||||
| 		d.dev.WriteCode(0, byte(p)|0xB8) | 		d.dev.WriteCode(0, byte(p)|0xB8) | ||||||
| 		d.dev.WriteCode(0, 0x13) | 		d.dev.WriteCode(0, 0x13) | ||||||
| 		for c := 0; c < 61; c++ { | 		for c := 0; c < 61; c++ { | ||||||
| 			//d.dev.WriteDatas(0, []byte{byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2)}) |  | ||||||
| 			//d.dev.WriteData(0, byte(0xF0^(0xFF*(c%2)))) |  | ||||||
| 			d.dev.WriteData(0, byte(rand.Int())) | 			d.dev.WriteData(0, byte(rand.Int())) | ||||||
| 			// d.dev.WriteData(0, 0xFF) |  | ||||||
| 			//d.dev.WriteData(0, byte(p*122+c)) |  | ||||||
| 			//time.Sleep(2 * time.Millisecond) |  | ||||||
| 		} | 		} | ||||||
| 		d.dev.WriteCode(1, byte(p)|0xB8) | 		d.dev.WriteCode(1, byte(p)|0xB8) | ||||||
| 		d.dev.WriteCode(1, 0x00) | 		d.dev.WriteCode(1, 0x00) | ||||||
| 		for c := 0; c < 61; c++ { | 		for c := 0; c < 61; c++ { | ||||||
| 			//d.dev.WriteDatas(1, []byte{byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2), byte(rand.Int() % 2)}) |  | ||||||
| 			d.dev.WriteData(1, byte(rand.Int())) | 			d.dev.WriteData(1, byte(rand.Int())) | ||||||
| 			// d.dev.WriteData(1, 0xFF) |  | ||||||
| 			//d.dev.WriteData(1, byte(4*int(p)+c)) |  | ||||||
| 			//d.dev.WriteData(1, byte(p*122+c+61)) |  | ||||||
| 			//d.dev.WriteData(1, byte(rand.Int())>>1) |  | ||||||
| 			//time.Sleep(2 * time.Millisecond) |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	d.status("9") |  | ||||||
| 	end := time.Now() | 	end := time.Now() | ||||||
| 	d.logger.Println(end.Sub(start)) | 	d.logger.Println(end.Sub(start)) | ||||||
| 	// for p := byte(0); p < 8; p++ { |  | ||||||
| 	// 	d.dev.WriteCodeL(p | 0xB8) |  | ||||||
| 	// 	d.dev.WriteCodeL(0x40) |  | ||||||
| 	// 	for c := 0; c < 64; c++ { |  | ||||||
| 	// 		d.dev.WriteDataL(Logo128[p][c]) |  | ||||||
| 	// 	} |  | ||||||
| 	// 	d.dev.WriteCodeR(p | 0xB8) |  | ||||||
| 	// 	d.dev.WriteCodeR(0x40) |  | ||||||
| 	// 	for c := 64; c < 128; c++ { |  | ||||||
| 	// 		d.dev.WriteDataR(Logo128[p][c]) |  | ||||||
| 	// 	} |  | ||||||
| 	// } |  | ||||||
| 	//d.dev.WriteCodeL(0xAF) // Display on |  | ||||||
| 	//d.dev.WriteCodeR(0xAF) // Display on |  | ||||||
| 	return nil | 	return nil | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -199,7 +174,7 @@ func (d *displayMt12232a) GetBounds() image.Rectangle { | |||||||
| 	return image.Rect(0, 0, 122, 32) | 	return image.Rect(0, 0, 122, 32) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *displayMt12232a) Flush(img *image.Gray) error { | func (d *displayMt12232a) FlushFull(img *image.Gray) error { | ||||||
| 	st := time.Now() | 	st := time.Now() | ||||||
|  |  | ||||||
| 	for p := byte(0); p < 4; p++ { | 	for p := byte(0); p < 4; p++ { | ||||||
| @@ -236,7 +211,83 @@ func (d *displayMt12232a) Flush(img *image.Gray) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *displayMt12232a) Close() error { | func (d *displayMt12232a) Flush(crystal, page byte) { | ||||||
|  | 	// !!! TODO Need to update GO to 1.23 to use .Or !!! | ||||||
|  | 	bit := uint32(1 << (crystal*4 + page)) | ||||||
|  | 	d.pagesFlushFlags.Store(d.pagesFlushFlags.Load() | bit) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *displayMt12232a) Close() error { | ||||||
|  | 	if d.flushCancel != nil { | ||||||
|  | 		d.flushCancel() | ||||||
|  | 		d.flushCancel = nil | ||||||
|  | 		<-d.flushDone | ||||||
|  | 	} | ||||||
| 	return d.dev.Close() | 	return d.dev.Close() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (d *displayMt12232a) flushLoop(ctx context.Context) { | ||||||
|  |  | ||||||
|  | 	for { | ||||||
|  | 		select { | ||||||
|  | 		case <-ctx.Done(): | ||||||
|  | 			close(d.flushDone) | ||||||
|  | 			return | ||||||
|  | 		case <-time.After(time.Millisecond): | ||||||
|  | 			forUpdate := d.pagesFlushFlags.Swap(0) | ||||||
|  | 			checkBit := uint32(1) | ||||||
|  | 			st := time.Now() | ||||||
|  | 			d.LockImg() | ||||||
|  | 			for p := byte(0); p < 4; p++ { | ||||||
|  | 				if forUpdate&(checkBit) != 0 { | ||||||
|  | 					d.dev.WriteCode(0, (3-p)|0xB8) | ||||||
|  | 					d.dev.WriteCode(0, 0x13) | ||||||
|  | 					for c := 0; c < 61; c++ { | ||||||
|  | 						d.dev.WriteDatas(0, []byte{ | ||||||
|  | 							d.img.Pix[int(p<<3+7)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+6)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+5)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+4)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+3)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+2)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+1)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+0)*122+c], | ||||||
|  | 						}) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				checkBit = checkBit << 1 | ||||||
|  | 			} | ||||||
|  | 			d.logger.Printf("%08b - %s\n", forUpdate, time.Since(st)) | ||||||
|  | 			for p := byte(0); p < 4; p++ { | ||||||
|  | 				if forUpdate&(checkBit) != 0 { | ||||||
|  | 					d.dev.WriteCode(1, (3-p)|0xB8) | ||||||
|  | 					d.dev.WriteCode(1, 0x00) | ||||||
|  | 					for c := 61; c < 122; c++ { | ||||||
|  | 						d.dev.WriteDatas(1, []byte{ | ||||||
|  | 							d.img.Pix[int(p<<3+7)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+6)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+5)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+4)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+3)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+2)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+1)*122+c], | ||||||
|  | 							d.img.Pix[int(p<<3+0)*122+c], | ||||||
|  | 						}) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				checkBit = checkBit << 1 | ||||||
|  | 			} | ||||||
|  | 			d.UnlockImg() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *displayMt12232a) GetImg() *image.Gray { | ||||||
|  | 	return d.img | ||||||
|  | } | ||||||
|  | func (d *displayMt12232a) LockImg() { | ||||||
|  | 	d.imgMutex.Lock() | ||||||
|  | } | ||||||
|  | func (d *displayMt12232a) UnlockImg() { | ||||||
|  | 	d.imgMutex.Unlock() | ||||||
|  | } | ||||||
|   | |||||||
| @@ -142,10 +142,19 @@ func (d *displayMt12864a) GetBounds() image.Rectangle { | |||||||
| 	return image.Rectangle{} | 	return image.Rectangle{} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *displayMt12864a) Flush(img *image.Gray) error { | func (d *displayMt12864a) Flush(crystal, page byte) { | ||||||
| 	return nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *displayMt12864a) Close() error { | func (d *displayMt12864a) Close() error { | ||||||
| 	return rpio.Close() | 	return rpio.Close() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (d *displayMt12864a) GetImg() *image.Gray { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | func (d *displayMt12864a) LockImg() { | ||||||
|  |  | ||||||
|  | } | ||||||
|  | func (d *displayMt12864a) UnlockImg() { | ||||||
|  |  | ||||||
|  | } | ||||||
|   | |||||||
| @@ -57,8 +57,8 @@ func (d *displaySsd1306) Test(ctx context.Context) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *displaySsd1306) Flush(img *image.Gray) error { | func (d *displaySsd1306) Flush(crystal, page byte) { | ||||||
| 	return d.dev.Draw(img.Bounds(), d.img, image.Point{}) | 	//return d.dev.Draw(img.Bounds(), d.img, image.Point{}) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *displaySsd1306) Close() error { | func (d *displaySsd1306) Close() error { | ||||||
| @@ -67,3 +67,13 @@ func (d *displaySsd1306) Close() error { | |||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (d *displaySsd1306) GetImg() *image.Gray { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | func (d *displaySsd1306) LockImg() { | ||||||
|  |  | ||||||
|  | } | ||||||
|  | func (d *displaySsd1306) UnlockImg() { | ||||||
|  |  | ||||||
|  | } | ||||||
|   | |||||||
| @@ -3,8 +3,8 @@ package drawer | |||||||
| import "math" | import "math" | ||||||
|  |  | ||||||
| func (d *drawer) FillBar(sx, sy, ex, ey, color int) { | func (d *drawer) FillBar(sx, sy, ex, ey, color int) { | ||||||
| 	d.Lock() | 	d.dev.LockImg() | ||||||
| 	defer d.Unlock() | 	defer d.dev.UnlockImg() | ||||||
|  |  | ||||||
| 	bounds := d.img.Bounds() | 	bounds := d.img.Bounds() | ||||||
| 	// Crop | 	// Crop | ||||||
| @@ -24,8 +24,8 @@ func (d *drawer) FillBar(sx, sy, ex, ey, color int) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (d *drawer) PutBar(sx, sy, ex, ey, color int) { | func (d *drawer) PutBar(sx, sy, ex, ey, color int) { | ||||||
| 	d.Lock() | 	d.dev.LockImg() | ||||||
| 	defer d.Unlock() | 	defer d.dev.UnlockImg() | ||||||
|  |  | ||||||
| 	bounds := d.img.Bounds() | 	bounds := d.img.Bounds() | ||||||
| 	// Crop | 	// Crop | ||||||
|   | |||||||
| @@ -2,26 +2,21 @@ package drawer | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"image" | 	"image" | ||||||
| 	"sync" |  | ||||||
|  |  | ||||||
| 	"gitea.unprism.ru/yotia/display-test/display" | 	"gitea.unprism.ru/yotia/display-test/display" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type drawer struct { | type drawer struct { | ||||||
| 	dev display.Display | 	dev display.Display | ||||||
|  |  | ||||||
| 	img *image.Gray | 	img *image.Gray | ||||||
| 	imgMutex sync.Mutex |  | ||||||
| } | } | ||||||
|  |  | ||||||
| type Drawer interface { | type Drawer interface { | ||||||
|  | 	GetDisplay() display.Display | ||||||
| 	// Lowlevel image |  | ||||||
| 	GetImg() *image.Gray |  | ||||||
| 	Lock() |  | ||||||
| 	Unlock() |  | ||||||
|  |  | ||||||
| 	Clear() | 	Clear() | ||||||
| 	Flush() error | 	Flush() | ||||||
|  |  | ||||||
| 	PutText(x, y int, text string) | 	PutText(x, y int, text string) | ||||||
|  |  | ||||||
| @@ -30,36 +25,35 @@ type Drawer interface { | |||||||
| } | } | ||||||
|  |  | ||||||
| func New(dev display.Display) Drawer { | func New(dev display.Display) Drawer { | ||||||
| 	return &drawer{ | 	d := &drawer{ | ||||||
| 		dev: dev, | 		dev: dev, | ||||||
| 		img: image.NewGray(dev.GetBounds()), |  | ||||||
| 	} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| func (d *drawer) GetImg() *image.Gray { | 	d.img = d.dev.GetImg() | ||||||
| 	return d.img | 	return d | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *drawer) Lock() { | func (d *drawer) GetDisplay() display.Display { | ||||||
| 	d.imgMutex.Lock() | 	return d.dev | ||||||
| } |  | ||||||
|  |  | ||||||
| func (d *drawer) Unlock() { |  | ||||||
| 	d.imgMutex.Unlock() |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *drawer) Clear() { | func (d *drawer) Clear() { | ||||||
| 	d.Lock() | 	d.dev.LockImg() | ||||||
| 	defer d.Unlock() | 	defer d.dev.UnlockImg() | ||||||
|  |  | ||||||
| 	for i := range d.img.Pix { | 	for i := range d.img.Pix { | ||||||
| 		d.img.Pix[i] = 0 | 		d.img.Pix[i] = 0 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *drawer) Flush() error { | func (d *drawer) Flush() { | ||||||
| 	d.Lock() | 	// Flush all pages | ||||||
| 	defer d.Unlock() | 	d.dev.Flush(0, 0) | ||||||
|  | 	d.dev.Flush(0, 1) | ||||||
| 	return d.dev.Flush(d.img) | 	d.dev.Flush(0, 2) | ||||||
|  | 	d.dev.Flush(0, 3) | ||||||
|  | 	d.dev.Flush(1, 0) | ||||||
|  | 	d.dev.Flush(1, 1) | ||||||
|  | 	d.dev.Flush(1, 2) | ||||||
|  | 	d.dev.Flush(1, 3) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										156
									
								
								drawer/font.go
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								drawer/font.go
									
									
									
									
									
								
							| @@ -143,70 +143,70 @@ var stdFont = []byte{ | |||||||
| 	0x41, 0x36, 0x8, 0x0, 0x0, // } | 	0x41, 0x36, 0x8, 0x0, 0x0, // } | ||||||
| 	0x8, 0x4, 0x8, 0x4, 0x0, // ~ | 	0x8, 0x4, 0x8, 0x4, 0x0, // ~ | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Hollow Up Arrow | 	0x0, 0x0, 0x0, 0x0, 0x0, // Hollow Up Arrow | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x55, 0x49, 0x55, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x0, 0x0, 0x0, 0x0, 0x0, // Empty | 	0x7f, 0x41, 0x41, 0x41, 0x7f, // Empty | ||||||
| 	0x7e, 0x11, 0x11, 0x7e, 0x0, // А | 	0x7e, 0x11, 0x11, 0x7e, 0x0, // А | ||||||
| 	0x7f, 0x49, 0x49, 0x31, 0x0, // Б | 	0x7f, 0x49, 0x49, 0x31, 0x0, // Б | ||||||
| 	0x7f, 0x49, 0x49, 0x36, 0x0, // В | 	0x7f, 0x49, 0x49, 0x36, 0x0, // В | ||||||
| @@ -280,21 +280,31 @@ func IntMin(a, b int) int { | |||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func IntMax(a, b int) int { | ||||||
|  | 	if a > b { | ||||||
|  | 		return a | ||||||
|  | 	} | ||||||
|  | 	return b | ||||||
|  | } | ||||||
|  |  | ||||||
| func (d *drawer) putChar(x0, y0 int, c byte) { | func (d *drawer) putChar(x0, y0 int, c byte) { | ||||||
| 	if int(c) > len(stdFont)/5 { | 	if int(c) > len(stdFont)/5 { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if y0 >= d.img.Rect.Dy() || x0 >= d.img.Rect.Dx() { | 	//if x0+7 < 0 || y0+5 < 0 || y0 >= d.img.Rect.Dy() || x0 >= d.img.Rect.Dx() { | ||||||
| 		return | 	//	return | ||||||
| 	} | 	//} | ||||||
|  |  | ||||||
| 	maxYi := IntMin(y0+7, d.img.Rect.Dy()) - y0 | 	minX := IntMax(x0, 0) - x0 | ||||||
| 	maxXi := IntMin(x0+5, d.img.Rect.Dx()) - x0 | 	minY := IntMax(y0, 0) - y0 | ||||||
|  |  | ||||||
| 	for yi := range maxYi { | 	maxY := IntMin(y0+7, d.img.Rect.Dy()) - y0 | ||||||
|  | 	maxX := IntMin(x0+5, d.img.Rect.Dx()) - x0 | ||||||
|  |  | ||||||
|  | 	for yi := minY; yi < maxY; yi++ { | ||||||
| 		lineaddr := (y0+yi)*d.img.Stride + x0 | 		lineaddr := (y0+yi)*d.img.Stride + x0 | ||||||
| 		for xi := range maxXi { | 		for xi := minX; xi < maxX; xi++ { | ||||||
| 			d.img.Pix[lineaddr+xi] = ((stdFont[int(c)*5+xi] >> yi) & 1) * 255 | 			d.img.Pix[lineaddr+xi] = ((stdFont[int(c)*5+xi] >> yi) & 1) * 255 | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -309,8 +319,8 @@ func convertStr(str string) []byte { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (d *drawer) PutText(x0, y0 int, text string) { | func (d *drawer) PutText(x0, y0 int, text string) { | ||||||
| 	d.Lock() | 	d.dev.LockImg() | ||||||
| 	defer d.Unlock() | 	defer d.dev.UnlockImg() | ||||||
|  |  | ||||||
| 	asciiStr := convertStr(text) | 	asciiStr := convertStr(text) | ||||||
| 	//asciiStr := []byte(text) | 	//asciiStr := []byte(text) | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								main.go
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"log" | 	"log" | ||||||
|  | 	"math" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/signal" | 	"os/signal" | ||||||
| 	"syscall" | 	"syscall" | ||||||
| @@ -48,7 +49,7 @@ func DrawProgress(ctx context.Context, timeout time.Duration) error { | |||||||
| 	// Draw outline | 	// Draw outline | ||||||
| 	x := 0 | 	x := 0 | ||||||
| 	y := drawer.FontCharH + 4 | 	y := drawer.FontCharH + 4 | ||||||
| 	w := d.GetImg().Rect.Dx() | 	w := dev.GetImg().Rect.Dx() | ||||||
| 	h := drawer.FontCharH - 4 | 	h := drawer.FontCharH - 4 | ||||||
|  |  | ||||||
| 	d.PutBar(x, y, x+w, y+h, 255) | 	d.PutBar(x, y, x+w, y+h, 255) | ||||||
| @@ -74,9 +75,7 @@ func DrawProgress(ctx context.Context, timeout time.Duration) error { | |||||||
| 			if value >= 1 { | 			if value >= 1 { | ||||||
| 				return nil | 				return nil | ||||||
| 			} | 			} | ||||||
| 			if err := d.Flush(); err != nil { | 			d.Flush() | ||||||
| 				return fmt.Errorf("display flush: %w", err) |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -95,11 +94,26 @@ func Init(ctx context.Context) error { | |||||||
|  |  | ||||||
| 	d.Clear() | 	d.Clear() | ||||||
| 	//d.FillBar(0, 0, 10, 10, 1) | 	//d.FillBar(0, 0, 10, 10, 1) | ||||||
| 	d.PutText(0, 0, "можно 4 строки впихнуть") | 	stTime := time.Now() | ||||||
| 	d.PutText(0, drawer.FontCharH+drawer.LineGap, "каждая буква 5x7") | 	for { | ||||||
| 	d.PutText(0, (drawer.FontCharH+drawer.LineGap)*2, "+ русский через жопу") | 		select { | ||||||
| 	d.PutText(0, (drawer.FontCharH+drawer.LineGap)*3, "KRBL forever!!") | 		case <-ctx.Done(): | ||||||
|  | 			return nil | ||||||
|  | 		default: | ||||||
|  | 			t := float64(time.Since(stTime).Milliseconds()) / 1000 | ||||||
|  | 			x := math.Sin(t)*10 + 5 | ||||||
|  | 			y := math.Cos(t)*10 + 5 | ||||||
|  | 			d.Clear() | ||||||
|  | 			d.PutText(int(x), int(y), "CGSG forever") | ||||||
|  | 			stT := time.Now() | ||||||
| 			d.Flush() | 			d.Flush() | ||||||
|  | 			logger.Println("Iteration time:", time.Since(stT)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	//d.PutText(0, 0, "можно 4 строки впихнуть") | ||||||
|  | 	//d.PutText(0, drawer.FontCharH+drawer.LineGap, "каждая буква 5x7") | ||||||
|  | 	//d.PutText(0, (drawer.FontCharH+drawer.LineGap)*2, "+ русский через жопу") | ||||||
|  | 	//d.PutText(0, (drawer.FontCharH+drawer.LineGap)*3, "KRBL forever!!") | ||||||
|  |  | ||||||
| 	// Modem init | 	// Modem init | ||||||
| 	//mInitCtx, mInitCtxCancel := context.WithCancel(ctx) | 	//mInitCtx, mInitCtxCancel := context.WithCancel(ctx) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user