• Android 8.1 关机充电动画(二)Uboot模式


    system:Android 8.1
    platform:RK3326/PX30
    uboot
    kernel


    Android 8.1 关机充电动画(一)模式选择
    Android 8.1 关机充电动画(二)Uboot模式
    Android 8.1 关机充电动画(三)Android模式


    前言

    这部分要涉及到uboot下关机充电动画的定制,属于比较low level的部分,所以代码修改的部分不大,在uboot中主要是对多张图片进行轮播,所以这里的主要工作是定位到相应的代码以及如何定制自己的动画。

    相关文档

    RK在uboot的开发方面已经给出了文档
    其中已经包括了这部分动画如何打包到rom中,不可避免的是需要重新编译uboot,但是图片会被打包到resource.img中。

    相关代码

    重新回到代码中u-boot/drivers/power/charge_animation.c

    struct charge_image {
    	const char *name;
    	int soc;
    	int period;	/* ms */
    };
    /*
     * IF you want to use your own charge images, please:
     *
     * 1. Update the following 'image[]' to point to your own images;
     * 2. You must set the failed image as last one and soc = -1 !!!
     */
    static const struct charge_image image[] = {
    	{ .name = "battery_0.bmp", .soc = 5, .period = 600 },
    	{ .name = "battery_1.bmp", .soc = 20, .period = 600 },
    	{ .name = "battery_2.bmp", .soc = 40, .period = 600 },
    	{ .name = "battery_3.bmp", .soc = 60, .period = 600 },
    	{ .name = "battery_4.bmp", .soc = 80, .period = 600 },
    	{ .name = "battery_5.bmp", .soc = 100, .period = 600 },
    	{ .name = "battery_fail.bmp", .soc = -1, .period = 1000 },
    };
    
    • name :文件名
    • soc:图片对应的电量百分比
    • period:图片显示的时间(单位:ms)

    那么,这里问题来了,图片如何打包到固件里呢?

    1. 先找到RK提供的打包用的脚本,u-boot/pack_resource.sh
    2. 找到需要打包的图片,然后需要修改的直接替换掉,图片采用8bit或24bit bmp格式,图片路径:u-boot/tools/images/,如下图所示: 在这里插入图片描述
    3. 最终就是如何打包图片了:
    cd u-boot && ./pack_resource.sh ../kernel/resource.img
    

    执行完以上命令后,终端会输出以下信息,说明打包成功;

    Pack ./tools/images/ & resource.img to resource.img ...
    Unpacking old image(resource.img):
    rk-kernel.dtb battery_1.bmp battery_2.bmp battery_3.bmp battery_4.bmp battery_5.bmp battery_fail.bmp logo.bmp logo_kernel.bmp battery_0.bmp
    Pack to resource.img successed!
    Packed resources:
    rk-kernel.dtb battery_1.bmp battery_2.bmp battery_3.bmp battery_4.bmp battery_5.bmp battery_fail.bmp logo.bmp logo_kernel.bmp battery_0.bmp
    resource.img is packed ready
    

    并且会在当前的路径下重新生成resource.img,将这个文件重新烧写到设备的对应分区,就可以把充电动画打包到设备的rom中了。

    总结

    简单介绍了RK平台上进行关机充电uboot模式下充电动画的定制和打包方法,篇幅较短,也可以参考RK官方的文档,下一篇介绍一下,关机充电Android模式下如何进行充电动画的修改。附录是充电动画显示的主要代码。


    附录

    下面的代码是函数static int charge_animation_show(struct udevice *dev)中的while(1),这里会一直循环显示充电图片;

    	/* Charging ! */
    	while (1) {
    		/*
    		 * At the most time, fuel gauge is usually a i2c device, we
    		 * should avoid read/write all the time. We had better set
    		 * poll seconds to update fuel gauge info.
    		 */
    		if (!first_poll_fg && get_timer(delta) < FUEL_GAUGE_POLL_MS)
    			goto show_images;
    
    		delta = get_timer(0);
    
    		debug("step1 (%d)... 
    ", screen_on);
    
    		/*
    		 * Most fuel gauge is I2C interface, it shouldn't be interrupted
    		 * during tansfer. The power key event depends on interrupt, so
    		 * so we should disable local irq when update fuel gauge.
    		 */
    		local_irq_disable();
    
    		/* Step1: Is charging now ? */
    		charging = fuel_gauge_get_chrg_online(fg);
    		if (charging <= 0) {
    			printf("Not charging, online=%d. Shutdown...
    ",
    			       charging);
    
    			/* wait uart flush before shutdown */
    			mdelay(5);
    
    			/* PMIC shutdown */
    			pmic_shutdown(pmic);
    
    			printf("Cpu should never reach here, shutdown failed !
    ");
    			continue;
    		}
    
    		debug("step2 (%d)... show_idx=%d
    ", screen_on, show_idx);
    
    		/* Step2: get soc and voltage */
    		soc = fuel_gauge_get_soc(fg);
    		if (soc < 0 || soc > 100) {
    			printf("get soc failed: %d
    ", soc);
    			continue;
    		}
    
    		voltage = fuel_gauge_get_voltage(fg);
    		if (voltage < 0) {
    			printf("get voltage failed: %d
    ", voltage);
    			continue;
    		}
    
    		current = fuel_gauge_get_current(fg);
    		if (current == -ENOSYS) {
    			printf("get current failed: %d
    ", current);
    			continue;
    		}
    		first_poll_fg = 0;
    
    		local_irq_enable();
    
    show_images:
    		/*
    		 * Just for debug, otherwise there will be nothing output which
    		 * is not good to know what happen.
    		 */
    		if (!debug_start)
    			debug_start = get_timer(0);
    		if (get_timer(debug_start) > 20000) {
    			debug_start = get_timer(0);
    			printf("[%8ld]: soc=%d%%, vol=%dmv, c=%dma, online=%d, screen_on=%d
    ",
    			       get_timer(0)/1000, soc, voltage,
    			       current, charging, screen_on);
    		}
    
    		/*
    		 * If ever lowpower screen off, force screen_on=false, which
    		 * means key event can't modify screen_on, only voltage higher
    		 * then threshold can update screen_on=true;
    		 */
    		if (ever_lowpower_screen_off)
    			screen_on = false;
    
    		/*
    		 * Auto turn on screen when voltage higher than Vol screen on.
    		 * 'ever_lowpower_screen_off' means enter while loop with
    		 * screen off.
    		 */
    		if ((ever_lowpower_screen_off) &&
    		    (voltage > pdata->screen_on_voltage)) {
    			ever_lowpower_screen_off = false;
    			screen_on = true;
    			show_idx = IMAGE_SHOW_RESET;
    		}
    
    		/*
    		 * IMAGE_SHOW_RESET means show_idx show be update by start_idx.
    		 * When short key pressed event trigged, we will set show_idx
    		 * as IMAGE_SHOW_RESET which updates images index from start_idx
    		 * that calculate by current soc.
    		 */
    		if (show_idx == IMAGE_SHOW_RESET) {
    			for (i = 0; i < image_num - 2; i++) {
    				/* Find out which image we start to show */
    				if ((soc >= image[i].soc) &&
    				    (soc < image[i + 1].soc)) {
    					start_idx = i;
    					break;
    				}
    
    				if (soc >= 100) {
    					start_idx = image_num - 2;
    					break;
    				}
    			}
    
    			debug("%s: show_idx=%d, screen_on=%d
    ",
    			      __func__, show_idx, screen_on);
    
    			/* Mark start index and start time */
    			show_idx = start_idx;
    			show_start = get_timer(0);
    		}
    
    		debug("step3 (%d)... show_idx=%d
    ", screen_on, show_idx);
    
    		/* Step3: show images */
    		if (screen_on) {
    			/* Don't call 'charge_show_bmp' unless image changed */
    			if (old_show_idx != show_idx) {
    				old_show_idx = show_idx;
    				debug("SHOW: %s
    ", image[show_idx].name);
    				charge_show_bmp(image[show_idx].name);
    			}
    			/* Re calculate timeout to off screen */
    			if (priv->auto_screen_off_timeout == 0)
    				priv->auto_screen_off_timeout = get_timer(0);
    		} else {
    			priv->auto_screen_off_timeout = 0;
    
    			system_suspend_enter(pdata);
    		}
    
    		mdelay(5);
    
    		/* Every image shows period */
    		if (get_timer(show_start) > image[show_idx].period) {
    			show_start = get_timer(0);
    			/* Update to next image */
    			show_idx++;
    			if (show_idx > (image_num - 2))
    				show_idx = IMAGE_SHOW_RESET;
    		}
    
    		debug("step4 (%d)... 
    ", screen_on);
    
    		/*
    		 * Step4: check key event.
    		 *
    		 * Short key event: turn on/off screen;
    		 * Long key event: show logo and boot system or still charging.
    		 */
    		key_state = check_key_press(dev);
    		if (key_state == KEY_PRESS_DOWN) {
    			old_show_idx = IMAGE_SHOW_RESET;
    
    			/* NULL means show nothing, ie. turn off screen */
    			if (screen_on)
    				charge_show_bmp(NULL);
    
    			/*
    			 * Clear current image index, and show image
    			 * from start_idx
    			 */
    			show_idx = IMAGE_SHOW_RESET;
    
    			/*
    			 * We turn off screen by charge_show_bmp(NULL), so we
    			 * should tell while loop to stop show images any more.
    			 *
    			 * If screen_on=false, means this short key pressed
    			 * event turn on the screen and we need show images.
    			 *
    			 * If screen_on=true, means this short key pressed
    			 * event turn off the screen and we never show images.
    			 */
    			if (screen_on)
    				screen_on = false;
    			else
    				screen_on = true;
    		} else if (key_state == KEY_PRESS_LONG_DOWN) {
    			/* Only long pressed while screen off needs screen_on true */
    			if (!screen_on)
    				screen_on = true;
    
    			/* Is able to boot now ? */
    			if (soc < pdata->exit_charge_level) {
    				printf("soc=%d%%, threshold soc=%d%%
    ",
    				       soc, pdata->exit_charge_level);
    				printf("Low power, unable to boot, charging...
    ");
    				show_idx = image_num - 1;
    				continue;
    			}
    
    			if (voltage < pdata->exit_charge_voltage) {
    				printf("voltage=%dmv, threshold voltage=%dmv
    ",
    				       voltage, pdata->exit_charge_voltage);
    				printf("Low power, unable to boot, charging...
    ");
    				show_idx = image_num - 1;
    				continue;
    			}
    
    			/* Success exit charging */
    			printf("Exit charge animation...
    ");
    			charge_show_logo();
    			break;
    		} else {
    			/* Do nothing */
    		}
    
    		debug("step5 (%d)... 
    ", screen_on);
    
    		/* Step5: Exit by ctrl+c */
    		if (ctrlc()) {
    			if (voltage >= pdata->screen_on_voltage)
    				charge_show_logo();
    			printf("Exit charge, due to ctrl+c
    ");
    			break;
    		}
    	}
    
  • 相关阅读:
    集合类提供的的方法
    集合相关常识
    day12练习题
    Django(重点)
    cookie和session
    admin的配置
    Django安装和配置环境变量
    django ORM创建数据库方法
    前端学习之jquery
    数据库基础
  • 原文地址:https://www.cnblogs.com/unclemac/p/12783399.html
Copyright © 2020-2023  润新知