import math from ScEpTIC.AST.builtins.builtin import Builtin from ScEpTIC.AST.elements.value import Value from ScEpTIC.emulator.energy.mcu import ADCPowerState from ScEpTIC.emulator.energy.mcu.options import MCUClockCycleAction from ScEpTIC.emulator.energy.options import OpModeName class voc_read_data(Builtin): """ voc_read_data() builtin that reads voc from SGP40 sensor """ def get_val(self): try: sgp40 = self._vmstate.config.analysis.energy.system_model.get_component('SGP40') except BaseException: raise Exception("SystemModel not attached to ScEpTIC") if sgp40 is None: raise Exception("SHT85 not attached to ScEpTIC") # read self._vmstate.global_clock += sgp40.simulate_read() class temperature_read_data(Builtin): """ temperature_read_data() builtin that reads temperature from SHT85 sensor """ def get_val(self): try: sht85 = self._vmstate.config.analysis.energy.system_model.get_component('SHT85') except BaseException: raise Exception("SystemModel not attached to ScEpTIC") if sht85 is None: raise Exception("SHT85 not attached to ScEpTIC") # read self._vmstate.global_clock += sht85.simulate_read() class camera_read_data(Builtin): """ camera_read_data() builtin that reads a camera """ def get_val(self): try: camera = self._vmstate.config.analysis.energy.system_model.get_component('0V7620') except BaseException: raise Exception("SystemModel not attached to ScEpTIC") if camera is None: raise Exception("Camera not attached to ScEpTIC") # word size self._vmstate.global_clock += camera.simulate_read(int(self.args[0])) class generic_adc_sensor_read(Builtin): """ generic_adc_sensor_read() builtin that reads a generic ADC sensor """ def get_val(self): try: generic_sensor = self._vmstate.config.analysis.energy.system_model.get_component('generic_sensor') except BaseException: raise Exception("SystemModel not attached to ScEpTIC") if generic_sensor is None: raise Exception("GenericADCSensor not attached to ScEpTIC") self._vmstate.global_clock += generic_sensor.simulate_read(int(self.args[0])) class cc1101_set_state(Builtin): """ cc1101_set_state() builtin that sets the state of cc1101 """ states = {0: 'off', 1: 'inactive', 2: 'active'} def get_val(self): try: cc1101 = self._vmstate.config.analysis.energy.system_model.get_component('cc1101') except BaseException: raise Exception("SystemModel not attached to ScEpTIC") if cc1101 is None: raise Exception("CC1101 not attached to ScEpTIC") self._vmstate.global_clock += cc1101.simulate_set_state(self.states[int(self.args[0])]) class cc1101_transmit(Builtin): """ cc1101_transmit() builtin that turns on the cc1101, transmit data, and turns it off """ def get_val(self): try: cc1101 = self._vmstate.config.analysis.energy.system_model.get_component('cc1101') except BaseException: raise Exception("SystemModel not attached to ScEpTIC") if cc1101 is None: raise Exception("CC1101 not attached to ScEpTIC") # args: bytes, word_size self._vmstate.global_clock += cc1101.simulate_transmit(int(self.args[0]), int(self.args[1])) class adc_off(Builtin): """ adc_off() builtin that turns off the ADCon """ def get_val(self): try: system_model = self._vmstate.config.analysis.energy.system_model except BaseException: raise Exception("SystemModel not attached to ScEpTIC") # Turn off ADC self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, OpModeName.SIMULATE_ADC) system_model.mcu.set_adc_state(ADCPowerState.OFF) class adc_on(Builtin): """ adc_on() builtin that turns on the ADC """ def get_val(self): try: system_model = self._vmstate.config.analysis.energy.system_model except BaseException: raise Exception("SystemModel not attached to ScEpTIC") # Turn on ADC # - Run instructions # - ADCPowerState -> ON for _ in range(system_model.mcu.adc_instructions['on']): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, OpModeName.SIMULATE_ADC) system_model.mcu.set_adc_state(ADCPowerState.ON) class adc_read(Builtin): """ adc_read() builtin that reads data from ADC """ def get_val(self): try: system_model = self._vmstate.config.analysis.energy.system_model except BaseException: raise Exception("SystemModel not attached to ScEpTIC") # Wait for startup and data to be ready for _ in range(system_model.mcu.get_ADC_wait_cycles()): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name) # Transfer for _ in range(system_model.mcu.adc_instructions['transfer']): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name) class adc_get_data(Builtin): """ adc_get_data(n_samples, wait_between_samples) builtin that turns the ADC on, collects n_samples (one every wait_between_samples ms), and turns the ADC off. """ op_mode_name = OpModeName.SIMULATE_ADC def __adc_on(self, system_model): # Turn on ADC # - Run instructions # - ADCPowerState -> ON for _ in range(system_model.mcu.adc_instructions['on']): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name) system_model.mcu.set_adc_state(ADCPowerState.ON) def __adc_off(self, system_model): # Turn off ADC self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name) system_model.mcu.set_adc_state(ADCPowerState.OFF) def __adc_transfer_data(self, system_model): # Wait for startup and data to be ready for _ in range(system_model.mcu.get_ADC_wait_cycles()): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name) # Transfer for _ in range(system_model.mcu.adc_instructions['transfer']): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name) def __wait_cycles(self, system_model, wait_cycles): if wait_cycles <= 0: return for _ in range(wait_cycles): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name) def __adc_get_samples_on_off(self, system_model, n_samples, wait_cycles): for i in range(n_samples): self.__adc_on(system_model) self.__adc_transfer_data(system_model) self.__adc_off(system_model) if i < (n_samples - 1): self.__wait_cycles(system_model, wait_cycles) def __adc_get_samples(self, system_model, n_samples, wait_cycles): self.__adc_on(system_model) for i in range(n_samples): self.__adc_transfer_data(system_model) if i < (n_samples - 1): self.__wait_cycles(system_model, wait_cycles) self.__adc_off(system_model) def get_val(self): try: system_model = self._vmstate.config.analysis.energy.system_model except BaseException: raise Exception("SystemModel not attached to ScEpTIC") # Samples to collect n_samples = self.args[0] # ms to wait between samples samples_s_wait = float(self.args[1]) / 1000.0 frequency = system_model.mcu.get_frequency() sample_wait_cycles = max(0, math.ceil(samples_s_wait*frequency) - system_model.mcu.get_ADC_wait_cycles()) wait_cycles = sample_wait_cycles - system_model.mcu.adc_instructions['on'] - 1 if self.args[2] == 0: self.__adc_get_samples(system_model, n_samples, sample_wait_cycles) else: self.__adc_get_samples_on_off(system_model, n_samples, wait_cycles) class timekeeper_get_time_us(Builtin): """ timekeeper_get_time_us() builtin that returns timekeeper power-off time in us """ def get_val(self): try: return self._vmstate.config.analysis.energy.system_model.timekeeper.get_time() * 1000000.0 except BaseException: raise Exception("SystemModel/Timekeeper not attached to ScEpTIC") class timekeeper_get_time(Builtin): """ timekeeper_get_time() builtin that returns timekeeper power-off time """ def get_val(self): try: return self._vmstate.config.analysis.energy.system_model.timekeeper.get_time() except BaseException: raise Exception("SystemModel/Timekeeper not attached to ScEpTIC") class set_mcu_power_on_voltage(Builtin): """ set_mcu_power_on_voltage() builtin that sets the power on voltage of the MCU """ def get_val(self): try: voltage = self.args[0] #print(f"Set MCU Von={voltage}V") return self._vmstate.config.analysis.energy.system_model.mcu.set_v_on(voltage) except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class get_mcu_time(Builtin): """ get_mcu_time() builtin that returns the mcu time """ def get_val(self): try: #t = self._vmstate.config.analysis.energy.system_model.mcu.get_time() #print(f"Time: {t}") return self._vmstate.config.analysis.energy.system_model.mcu.get_time() except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class get_mcu_time_us(Builtin): """ get_mcu_time_us() builtin that returns the mcu time in us """ def get_val(self): try: return self._vmstate.config.analysis.energy.system_model.mcu.get_time() * 1000000 except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class set_mcu_time(Builtin): """ set_mcu_time() builtin that sets the mcu time """ def get_val(self): try: t = float(self.args[0]) self._vmstate.config.analysis.energy.system_model.mcu.set_time(t) except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class set_mcu_time_us(Builtin): """ set_mcu_time_us() builtin that sets the mcu time in us """ def get_val(self): try: t = float(self.args[0]) / 1000000.0 self._vmstate.config.analysis.energy.system_model.mcu.set_time(t) except BaseException as e: print(self.args) print(e) raise Exception("SystemModel/MCU not attached to ScEpTIC") class get_simulation_time(Builtin): """ get_simulation_time() builtin that returns the simulation time """ print_enabled = False def get_val(self): try: t = self._vmstate.config.analysis.energy.system_model.get_simulation_time() if self.print_enabled: t_us = t * 1000000.0 print(f"Time (us): {round(t_us, 2)}") return t except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class reset_simulation_time(Builtin): """ reset_simulation_time() builtin that resets the simulation time """ def get_val(self): try: self._vmstate.config.analysis.energy.system_model.reset_simulation_time() except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class get_mcu_clock_cycles(Builtin): """ get_mcu_clock_cycles() builtin that returns the number of clock cycles in the latest active cycle """ def get_val(self): try: return self._vmstate.config.analysis.energy.system_model.mcu.get_clock_cycles() except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class get_used_energy(Builtin): """ get_used_energy() builtin that returns the used energy """ print_enabled = False def get_val(self): try: e = self._vmstate.config.analysis.energy.system_model.get_used_energy() if self.print_enabled: e_uj = e * 1000000.0 print(f"Energy consumption (uJ): {round(e_uj, 2)}") return e except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class set_capacitor_voltage(Builtin): """ set_voltage() bultin that sets the energy buffer voltage """ def get_val(self): try: system_model = self._vmstate.config.analysis.energy.system_model except BaseException: raise Exception("SystemModel not attached to ScEpTIC") system_model.energy_buffer.set_voltage(self.args[0]) class reset_used_energy(Builtin): """ reset_energy() builtin that resets the energy consumption """ def get_val(self): try: self._vmstate.config.analysis.energy.system_model.reset_used_energy() except BaseException: raise Exception("SystemModel/MCU not attached to ScEpTIC") class get_capacitor_voltage(Builtin): """ get_voltage() builtin that returns capacitor voltage """ def get_val(self): try: system_model = self._vmstate.config.analysis.energy.system_model except BaseException: raise Exception("SystemModel not attached to ScEpTIC") op_mode_name = OpModeName.PROBE_ENERGY_BUFFER # Turn on ADC # - Run instructions # - ADCPowerState -> ON for _ in range(system_model.mcu.adc_instructions['on']): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, op_mode_name) system_model.mcu.set_adc_state(ADCPowerState.ON) # Wait for startup and data to be ready for _ in range(system_model.mcu.get_ADC_wait_cycles()): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, op_mode_name, True) # Transfer data to reg for _ in range(system_model.mcu.adc_instructions['transfer']): self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, op_mode_name) v = system_model.energy_buffer.get_voltage() # Turn off ADC self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, op_mode_name) system_model.mcu.set_adc_state(ADCPowerState.OFF) return v get_capacitor_voltage.define_builtin('sceptic_get_capacitor_voltage', '', 'double') set_capacitor_voltage.define_builtin('sceptic_set_capacitor_voltage', 'double', 'void') get_mcu_clock_cycles.define_builtin('sceptic_get_mcu_clock_cycles', '', 'i32') get_mcu_time.define_builtin('sceptic_get_mcu_time', '', 'double') get_mcu_time_us.define_builtin('sceptic_get_mcu_time_us', '', 'double') get_used_energy.define_builtin('sceptic_get_used_energy', '', 'double') reset_used_energy.define_builtin('sceptic_reset_used_energy', '', 'void') get_simulation_time.define_builtin('sceptic_get_simulation_time', '', 'double') set_mcu_time.define_builtin('sceptic_set_mcu_time', 'double', 'void') set_mcu_time_us.define_builtin('sceptic_set_mcu_time_us', 'double', 'void') reset_simulation_time.define_builtin('sceptic_reset_simulation_time', '', 'void') # voltage set_mcu_power_on_voltage.define_builtin('sceptic_set_mcu_power_on_voltage', 'double', 'void') timekeeper_get_time.define_builtin('sceptic_timekeeper_get_time', '', 'double') timekeeper_get_time_us.define_builtin('sceptic_timekeeper_get_time_us', '', 'double') # n_samples, t_wait (ms), on_off adc_get_data.define_builtin('sceptic_adc_get_data', 'i32, double, i32', 'void') adc_on.define_builtin('sceptic_adc_on', '', 'void') adc_off.define_builtin('sceptic_adc_off', '', 'void') adc_read.define_builtin('sceptic_adc_read', '', 'void') # bytes, word_size cc1101_transmit.define_builtin('sceptic_cc1101_transmit', 'i32, i32', 'void') # state_id cc1101_set_state.define_builtin('sceptic_cc1101_set_state', 'i32', 'void') # n_samples generic_adc_sensor_read.define_builtin('sceptic_generic_adc_sensor_read', 'i32', 'void') # word size camera_read_data.define_builtin('sceptic_camera_read_data', 'i32', 'void') temperature_read_data.define_builtin('sceptic_read_temperature', '', 'void') voc_read_data.define_builtin('sceptic_read_voc', '', 'void')