split this python code in multiple functions to make it more readable:
def read_char_device_benchmark_on_file(): #TODO: add the orientation matices
	'''
	Computes the scaling factor for the data read by the gyroscope.
	The scaling factor depends on the resolution mode (high res or not) and the gyroscope 
	'''

	# get the boot time, needed for timestamping:
	boot_time = datetime.fromtimestamp(time.time() - time.monotonic(), timezone.utc)
	boot_time = boot_time + timedelta(seconds = GPS_TIME_TO_UTC_LEAP_SECONDS) #We want our timestamps in gps time

	# for data from driver
	iio_read_buf = bytearray(2048)
	iio_read_size = 0

	# scaling factors:
	accel_scale = compute_accel_scaling_factor()
	gyro_scale = compute_gyro_scaling_factor()

	# open the char device
	iio_fd = os.open("/dev/iio:device0", os.O_RDONLY)

	start_time = time.perf_counter()
	tempString = []

	while time.perf_counter()-start_time < 10:
		# read data from char device
		nbytes = len(iio_read_buf) - iio_read_size
		data = os.read(iio_fd, nbytes)
		if not data:
			print("no data in buffer")
			exit()

		iio_read_buf[iio_read_size:iio_read_size+len(data)] = data
		iio_read_size += len(data)

		# parse data
		ptr = 0
		left_over = 0
		while ptr < iio_read_size:
			rdata = iio_read_buf[ptr:]
			header = struct.unpack("<H", rdata[:2])[0]
			if header == END_MARKER:
				if (iio_read_size - ptr) < END_MARKER_SIZE:
					left_over = iio_read_size - ptr
					break
				ptr += END_MARKER_SIZE
			elif header == EMPTY_MARKER:
				if (iio_read_size - ptr) < EMPTY_MARKER_SIZE:
					left_over = iio_read_size - ptr
					break
				ptr += EMPTY_MARKER_SIZE
			elif header == GYRO_HDR:
				if (iio_read_size - ptr) < GYRO_DATA_SIZE:
					left_over = iio_read_size - ptr
					break
				gyro = struct.unpack("<3i", rdata[4:16])
				gyro_ts = struct.unpack("<q", rdata[16:24])[0]
				timestamp = (
					boot_time + timedelta(microseconds=round(gyro_ts / 1000))
				).strftime("%Y%m%d%H%M%S.%f")
				tempString.append(f"G | {timestamp} | {tuple(g * gyro_scale for g in gyro)}")
				ptr += GYRO_DATA_SIZE
			elif header == ACCEL_HDR:
				if (iio_read_size - ptr) < ACCEL_DATA_SIZE:
					left_over = iio_read_size - ptr
					break
				accel = struct.unpack("<3i", rdata[4:16])
				accel_ts = struct.unpack("<q", rdata[16:24])[0]
				timestamp = (
					boot_time + timedelta(microseconds=round(accel_ts / 1000))
				).strftime("%Y%m%d%H%M%S.%f")
				tempString.append(f"A | {timestamp} | {tuple(a * accel_scale for a in accel)}")
				ptr += ACCEL_DATA_SIZE
			else:
				ptr += 1

		if left_over > 0:
			# create a new ctypes array and copy the data from bytearray
			iio_read_buf_ctypes = (ctypes.c_char * len(iio_read_buf)).from_buffer_copy(iio_read_buf)

			# use iio_read_buf_ctypes instead of iio_read_buf in ctypes.memmove()
			ctypes.memmove(ctypes.cast(iio_read_buf_ctypes, ctypes.c_void_p).value, ctypes.cast(ctypes.addressof(iio_read_buf_ctypes) + ptr, ctypes.c_void_p).value, left_over)
			# copy the data back to the original bytearray
			iio_read_buf[:] = bytearray(iio_read_buf_ctypes)

			iio_read_size = left_over
		else:
			iio_read_size = 0
	with open("datalog.txt", "wt") as log:
		for sample in tempString:
			log.write(f"{sample}\n")