Created
October 12, 2018 09:44
-
-
Save shikarunochi/faac47931052a028e5f8080adf857f53 to your computer and use it in GitHub Desktop.
M5Stack Spinner for Arduino
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <M5Stack.h> | |
#include <SD.h> | |
#include <Wire.h> | |
#include <JPEGDecoder.h> | |
#define PI 3.141592653589793 | |
const int DOT_SIZE = 5; | |
#define SIZE_X 48 | |
#define SIZE_Y 48 | |
uint16_t cgData[SIZE_X][SIZE_Y] = { | |
}; | |
float angle; | |
const float deltaAngle = 5; | |
int delayValue; | |
boolean flag1000; | |
void renderJPEG(); | |
#define minimum(a,b) (((a) < (b)) ? (a) : (b)) | |
//データ生成 | |
void setup() { | |
Serial.begin(115200); // SERIAL | |
M5.begin(); // M5STACK INITIALIZE | |
M5.Lcd.setBrightness(200); // BRIGHTNESS = MAX 255 | |
M5.Lcd.fillScreen(BLACK); // CLEAR SCREEN | |
delay(3000); | |
SD.begin(); | |
Serial.print("SD Begin"); | |
Serial.print("InitialStart"); | |
//ファイル名は"M5StackSpinner48x48.jpg"固定です。 | |
File jpgFile = SD.open( "/M5StackSpinner48x48.jpg", FILE_READ); | |
if(!jpgFile){ | |
Serial.println("File not exist"); | |
M5.Lcd.print("File not exist."); | |
while(1); | |
} | |
JpegDec.decodeSdFile(jpgFile); | |
renderJPEG(); | |
Serial.print("InitialEnd"); | |
angle = 0; | |
delayValue = 2800;//microSeconds | |
flag1000 = false; | |
} | |
int drawLine(float angle){ //角度 angle の向きで、データ中心からMAX(24*1.4 = 34)ドットの絵を描く | |
int color = 0; | |
int xPos = 120 - DOT_SIZE / 2; | |
for(int yCount = 0;yCount < 34;yCount++){ | |
//中心から、角度 angle度にyCount | |
int x = (int)((float)yCount * cos(angle/(180/PI))) + 24; | |
int y = (int)((float)yCount * sin(angle/(180/PI))) + 24; | |
uint16_t color = 0; | |
if(x >= 0 && x< 48 && y >= 0 && y < 48){//ドットデータ外なら色は黒 | |
color = cgData[x][y]; | |
} | |
//中心から外向きに描く | |
M5.Lcd.fillRect(160 + yCount * DOT_SIZE - DOT_SIZE / 2, xPos ,DOT_SIZE, DOT_SIZE * 2 , color); //縦倍 | |
xPos = xPos + DOT_SIZE / 5 * 3; | |
//Serial.print("Angle:"); | |
//Serial.print(angle); | |
//Serial.print(": yCount:"); | |
//Serial.print(yCount); | |
//Serial.print(": x:"); | |
//Serial.print(x); | |
//Serial.print(": y:"); | |
//Serial.print(y); | |
//Serial.print(": color:"); | |
//Serial.print(cgData[x][y]); | |
//Serial.print("\n"); | |
} | |
} | |
void displayDelay(){ | |
if(delayValue < 0){delayValue = 0;} | |
M5.Lcd.fillRect(0, 0, 50, 20, BLACK); | |
M5.Lcd.setCursor(0, 0); | |
M5.Lcd.printf("%1.1f",delayValue / 1000.0); | |
if(flag1000){ | |
M5.Lcd.setCursor(0, 10); | |
M5.Lcd.print("[x10]"); | |
} | |
} | |
//表示 | |
void loop() { | |
drawLine(angle); | |
angle = angle + deltaAngle; | |
if(angle >=360){ | |
angle = 0; | |
} | |
if(M5.BtnA.wasPressed()){ | |
if(flag1000){ | |
delayValue = delayValue - 1000; | |
flag1000 = false; | |
}else{ | |
delayValue = delayValue - 100; | |
} | |
displayDelay(); | |
} | |
if(M5.BtnB.wasPressed()){ | |
flag1000 = !flag1000; | |
displayDelay(); | |
} | |
if(M5.BtnC.wasPressed()){ | |
if(flag1000){ | |
delayValue = delayValue + 1000; | |
flag1000 = false; | |
}else{ | |
delayValue = delayValue + 100; | |
} | |
displayDelay(); | |
} | |
M5.update(); | |
delayMicroseconds(delayValue); | |
} | |
void testPrint(){ | |
for(int x = 0;x < 32;x++){ | |
for(int y = 0;y < 32;y++){ | |
M5.Lcd.fillRect(x * 4, y * 4 , 4, 4, cgData[x][y]); | |
} | |
} | |
M5.update(); | |
while(1); | |
} | |
void renderJPEG() { | |
// retrieve infomration about the image | |
uint16_t *pImg; | |
uint16_t mcu_w = JpegDec.MCUWidth; | |
uint16_t mcu_h = JpegDec.MCUHeight; | |
uint32_t max_x = JpegDec.width; | |
uint32_t max_y = JpegDec.height; | |
// Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) | |
// Typically these MCUs are 16x16 pixel blocks | |
// Determine the width and height of the right and bottom edge image blocks | |
uint32_t min_w = minimum(mcu_w, max_x % mcu_w); | |
uint32_t min_h = minimum(mcu_h, max_y % mcu_h); | |
// save the current image block size | |
uint32_t win_w = mcu_w; | |
uint32_t win_h = mcu_h; | |
// record the current time so we can measure how long it takes to draw an image | |
uint32_t drawTime = millis(); | |
// save the coordinate of the right and bottom edges to assist image cropping | |
// to the screen size | |
//max_x += xpos; | |
//max_y += ypos; | |
// read each MCU block until there are no more | |
while ( JpegDec.read()) { | |
// save a pointer to the image block | |
pImg = JpegDec.pImage; | |
// calculate where the image block should be drawn on the screen | |
int mcu_x = JpegDec.MCUx * mcu_w;// + xpos; | |
int mcu_y = JpegDec.MCUy * mcu_h;// + ypos; | |
// check if the image block size needs to be changed for the right and bottom edges | |
if (mcu_x + mcu_w <= max_x) win_w = mcu_w; | |
else win_w = min_w; | |
if (mcu_y + mcu_h <= max_y) win_h = mcu_h; | |
else win_h = min_h; | |
// calculate how many pixels must be drawn | |
uint32_t mcu_pixels = win_w * win_h; | |
// draw image block if it will fit on the screen | |
if ( ( mcu_x + win_w) <= SIZE_X && ( mcu_y + win_h) <= SIZE_Y) { | |
// open a window onto the screen to paint the pixels into | |
//TFTscreen.setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1); | |
for(int by = mcu_y;by < mcu_y + win_h;by++){ | |
for(int bx = mcu_x;bx < mcu_x + win_w;bx++){ | |
if(bx < SIZE_X && by < SIZE_Y){ | |
cgData[bx][by] = *pImg; | |
} | |
*pImg++; | |
} | |
} | |
//TFTscreen.setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1); | |
// push all the image block pixels to the screen | |
//while (mcu_pixels--) TFTscreen.pushColor(*pImg++); // Send to TFT 16 bits at a time | |
} | |
// stop drawing blocks if the bottom of the screen has been reached | |
// the abort function will close the file | |
else if ( ( mcu_y + win_h) >= SIZE_Y) JpegDec.abort(); | |
} | |
// calculate how long it took to draw the image | |
drawTime = millis() - drawTime; // Calculate the time it took | |
// print the results to the serial port | |
Serial.print ("Total render time was : "); Serial.print(drawTime); Serial.println(" ms"); | |
Serial.println("====================================="); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment