view src/cs/services/buzm/buzm_process.c @ 297:8dfdf88d632f

BUZM SWE initial implementation
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 29 Mar 2022 03:45:41 +0000
parents
children
line wrap: on
line source

/*
 * In this module we are going to implement the main process functions
 * for BUZM.
 */

#include "buzm/buzm_env.h"
#include "buzm/buzm_func_i.h"
#include "rv/rv_general.h"
#include "rvf/rvf_api.h"
#include "rvm/rvm_use_id_list.h"
#include "ffs/ffs_api.h"
#include "main/sys_types.h"
#include "buzzer/pwt.h"

static void stop_current_melody(void)
{
	PWT_stop_tone();
	rvf_stop_timer(BUZM_TIMER);
	PWT_block_off();
	ffs_close(buzm_env->ffs_fd);
	buzm_env->melody_running = FALSE;
}

void buzm_process_start_req(struct buzm_start_msg *msg)
{
	T_FFS_SIZE rdsize;

	/* stop any previous melody first */
	if (buzm_env->melody_running) {
		stop_current_melody();
		rvf_send_trace("Melody play interrupted by new melody start",43,
				NULL_PARAM, RV_TRACE_LEVEL_DEBUG_MEDIUM,
				BUZM_USE_ID);
	}
	rdsize = ffs_read(msg->fd, (void *) buzm_env->chunk_buf,
			  sizeof(struct melody_entry) * MELODY_CHUNK_SIZE);
	if (rdsize < sizeof(struct melody_entry)) {
		ffs_close(msg->fd);
		rvf_send_trace("Error: invalid melody file", 26, NULL_PARAM,
				RV_TRACE_LEVEL_ERROR, BUZM_USE_ID);
		return;
	}
	/* start this melody */
	rvf_send_trace("Starting PWT melody play", 24, NULL_PARAM,
			RV_TRACE_LEVEL_DEBUG_LOW, BUZM_USE_ID);
	PWT_block_on();
	buzm_env->melody_running = TRUE;
	buzm_env->ffs_fd = msg->fd;
	buzm_env->play_volume = msg->volume;
	buzm_env->loop_mode = msg->loop;
	buzm_env->chunk_play_ptr = 0;
	buzm_env->chunk_end_ptr = rdsize / sizeof(struct melody_entry);
	buzm_env->melody_end_flag = FALSE;
	rvf_start_timer(BUZM_TIMER, 1, FALSE);
}

void buzm_process_stop_req(struct buzm_stop_msg *msg)
{
	if (buzm_env->melody_running) {
		stop_current_melody();
		rvf_send_trace("Melody play stopped by command", 30,
				NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW,
				BUZM_USE_ID);
	} else {
		rvf_send_trace("Redundant melody play stop command", 34,
				NULL_PARAM, RV_TRACE_LEVEL_DEBUG_MEDIUM,
				BUZM_USE_ID);
	}
}

static void melody_loop_restart(void)
{
	T_FFS_SIZE rdsize;

	ffs_seek(buzm_env->ffs_fd, 0, FFS_SEEK_SET);
	rdsize = ffs_read(buzm_env->ffs_fd, (void *) buzm_env->chunk_buf,
			  sizeof(struct melody_entry) * MELODY_CHUNK_SIZE);
	if (rdsize < sizeof(struct melody_entry)) {
		rvf_send_trace("Bad melody file on loop restart!", 32,
				NULL_PARAM, RV_TRACE_LEVEL_ERROR, BUZM_USE_ID);
		PWT_block_off();
		ffs_close(buzm_env->ffs_fd);
		buzm_env->melody_running = FALSE;
		return;
	}
	buzm_env->chunk_play_ptr = 0;
	buzm_env->chunk_end_ptr = rdsize / sizeof(struct melody_entry);
	buzm_env->melody_end_flag = FALSE;
	rvf_start_timer(BUZM_TIMER, 1, FALSE);
}

static void melody_normal_finish(void)
{
	PWT_block_off();
	ffs_close(buzm_env->ffs_fd);
	buzm_env->melody_running = FALSE;
	rvf_send_trace("Melody play finished", 20, NULL_PARAM,
			RV_TRACE_LEVEL_DEBUG_LOW, BUZM_USE_ID);
}

static void melody_end_process(void)
{
	if (buzm_env->loop_mode)
		melody_loop_restart();
	else
		melody_normal_finish();
}

void buzm_handle_timer(void)
{
	struct melody_entry *curnote;
	UINT8 pwt_vol;
	T_FFS_SIZE rdsize;

	/* weed out any spurious timer hits */
	if (!buzm_env->melody_running)
		return;
	/* real end of previous note or rest */
	PWT_stop_tone();
	if (buzm_env->melody_end_flag) {
		melody_end_process();
		return;
	}
	curnote = buzm_env->chunk_buf + buzm_env->chunk_play_ptr;
	if (curnote->note_volume) {
		pwt_vol = ((buzm_env->play_volume * curnote->note_volume + 63)
			   >> 6) - 1;
		PWT_play_tone(curnote->pwt_note, pwt_vol);
	}
	rvf_start_timer(BUZM_TIMER, curnote->duration, FALSE);
	buzm_env->chunk_play_ptr++;
	if (buzm_env->chunk_play_ptr < buzm_env->chunk_end_ptr)
		return;
	/* do we have more? */
	rdsize = ffs_read(buzm_env->ffs_fd, (void *) buzm_env->chunk_buf,
			  sizeof(struct melody_entry) * MELODY_CHUNK_SIZE);
	if (rdsize < sizeof(struct melody_entry))
		buzm_env->melody_end_flag = TRUE;
	else {
		buzm_env->chunk_play_ptr = 0;
		buzm_env->chunk_end_ptr = rdsize / sizeof(struct melody_entry);
	}
}