Skip to content

Instantly share code, notes, and snippets.

@kdrag0n
Last active December 24, 2019 22:23
Show Gist options
  • Save kdrag0n/ffc2bd18ae10ad5f3110795d6dbb38f5 to your computer and use it in GitHub Desktop.
Save kdrag0n/ffc2bd18ae10ad5f3110795d6dbb38f5 to your computer and use it in GitHub Desktop.
An experimental OPP power usage and EAS energy model calculator for use with consumer Android devices. Written in Python.
#!/usr/bin/env python
#
# OPP Power Usage and EAS Energy Model Calculator
# by @kdrag0n
# for Android devices
#
# This program is licensed under the MIT License (MIT)
#
# Copyright (c) 2019 Danny Lin <[email protected]>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
import sys
from enum import Enum
#######################
# CONSTANTS TO EDIT #
#######################
freq_l = [300000,403200,480000,576000,652800,748800,825600,902400,979200,1056000,1132800,1228800,1324800,1420800,1516800,1612800,1689600,1766400]
freq_b = [825600,902400,979200,1056000,1209600,1286400,1363200,1459200,1536000,1612800,1689600,1766400,1843200,1920000,1996800,2092800,2169600,2246400,2323200,2400000,2476800,2553600,2649600] #,2707200,2764800,2784000,2803200]
mv_l = [592,592,592,592,592,592,604,612,616,620,632,644,668,700,732,772,792,820]
mv_b = [608,624,636,652,664,676,700,708,728,744,760,788,804,816,840,872,896,900,924,948,972,992,1024,1024,1060,1076,1088]
ma_l = [2.27,3.63,4.36,5.21,5.47,6.74,7.69,8.57,9.42,10.41,11.56,12.87,14.61,16.49,18.90,21.62,24.47,26.45]
ma_b = [28.88,32.40,36.46,39.99,47.23,51.39,56.90,64.26,69.65,75.14,83.16,91.75,100.66,111.45,122.23,143.54,147.54,153.09,166.44,184.69,204.14,223.37,253.77]
cpu_cluster0_active_ma = 1.30
cpu_cluster4_active_ma = 5.29
###################################
# DO NOT EDIT BEYOND THIS POINT #
###################################
# All possible modes of operation
class Mode(Enum):
NORMAL = 1
CSV = 2
EAS = 3
# Find the closest value to `target` in `list_src`
def find_closest(list_src, target):
return min(list_src, key=lambda x: abs(x - target))
# Calculate the power usage for a given OPP in mW
def calc_freq_mw(idx, mv_src, ma_src, cluster_active_ma):
mv_opp = mv_src[idx] # Get the corresponding mV
ma_opp = ma_src[idx] # Get the corresponding mA
ma_final = ma_opp + cluster_active_ma # total mA = freq mA + cluster mA
uw_final = mv_opp * ma_final # mV * mA = uW
mw_final = uw_final / 1000 # uW / 1000 = mW
return mw_final
# Print the power usage for each OPP
def print_opp_mw(freq_src, mv_src, ma_src, cluster_active_ma, mode):
if mode == Mode.CSV: # Print a header for the following CSV columns
print('Frequency,Power usage')
power_map = {} # Contains [freq_khz] = mW
# If eas_mode, it will be overridden to [freq_khz] = 0.1 W
for idx, freq_khz in enumerate(freq_src): # Calculate the power consumption in mW for each OPP
mw_final = calc_freq_mw(idx, mv_src, ma_src, cluster_active_ma)
power_map[freq_khz] = mw_final
if mode == Mode.EAS: # Normalize mW values into values suitable for use in an EAS Energy Model
for freq_khz, power in power_map.items():
power *= 100 # Scale it up for less precision loss when rounding to int
power_map[freq_khz] = power # Update it
for freq_khz, power in power_map.items():
if mode == Mode.CSV: # Print values in CSV format for spreadsheet use
print('%d,%f' % (freq_khz, power))
elif mode == Mode.EAS: # Print values separated such that they can be easily incorporated in an EAS EM
print('%d %.0f' % (freq_khz, power))
else: # Pretty-print values for human use
freq_mhz = freq_khz / 1000 # Format the frequency as MHz instead of KHz for readability
print('%.1f MHz: %.1f mW' % (freq_mhz, power))
def print_opp_pair_mw(approx_freq_l, approx_freq_b):
# Obtain the necessary information to format the message
freq_l_khz = find_closest(freq_l, approx_freq_l)
freq_b_khz = find_closest(freq_b, approx_freq_b)
freq_l_idx = freq_l.index(freq_l_khz)
freq_b_idx = freq_b.index(freq_b_khz)
# Calculate the power consumption for each individual value in mW
mw_l = calc_freq_mw(freq_l_idx, mv_l, ma_l, cpu_cluster0_active_ma)
mw_b = calc_freq_mw(freq_b_idx, mv_b, ma_b, cpu_cluster4_active_ma)
# Prepare the final values to display
freq_l_mhz = freq_l_khz / 1000
freq_b_mhz = freq_b_khz / 1000
mw_total = mw_l + mw_b
# Pretty-print the result since this is an interactive prompt
print('%.1f MHz + %.1f MHz = %.1f mW' % (freq_l_mhz, freq_b_mhz, mw_total))
# The main entry point
def main():
# Detect which mode of operation is desired
mode = Mode.NORMAL
if len(sys.argv) > 1:
if sys.argv[1] == 'csv':
mode = Mode.CSV
elif sys.argv[1] == 'eas':
mode = Mode.EAS
# Print all OPP power usages for the little cluster
print('Little cluster:')
print_opp_mw(freq_l, mv_l, ma_l, cpu_cluster0_active_ma, mode)
# Print all OPP power usages for the big cluster
print('\nBig cluster:')
print_opp_mw(freq_b, mv_b, ma_b, cpu_cluster4_active_ma, mode)
# Interactive frequency pair power usage calculator prompt
print('\n\nPair calculator')
while True:
inp_freq_l = int(input('Little freq in MHz: ')) * 1000 # convert input to rough KHz
inp_freq_b = int(input('Big freq in MHz: ')) * 1000 # convert input to rough KHz
print_opp_pair_mw(inp_freq_l, inp_freq_b) # Output the power usage for the given OPP pair
print()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment