changeset 297:8dfdf88d632f

BUZM SWE initial implementation
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 29 Mar 2022 03:45:41 +0000
parents a927f030a4e0
children b1935a9ee04e
files components/buzm configure.sh scripts/config-headers.sh scripts/make-rv-swe-hdr.sh src/cs/services/buzm/buzm_api.c src/cs/services/buzm/buzm_api.h src/cs/services/buzm/buzm_env.c src/cs/services/buzm/buzm_env.h src/cs/services/buzm/buzm_func_i.h src/cs/services/buzm/buzm_handle_message.c src/cs/services/buzm/buzm_messages_i.h src/cs/services/buzm/buzm_pool_size.h src/cs/services/buzm/buzm_process.c src/cs/services/buzm/buzm_struct_i.h src/cs/services/buzm/buzm_task.c targets/c11x.conf targets/c139.conf
diffstat 17 files changed, 600 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/buzm	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,42 @@
+# Building BUZM SWE - an original FreeCalypso addition
+
+CFLAGS="-mn -mt -o -x -mw -me -pw2"
+CPPFLAGS="-DTOOL_CHOICE=0 -D_TMS470"
+
+# Includes
+
+CPPFLAGS="$CPPFLAGS -I$SRC/nucleus"
+CPPFLAGS="$CPPFLAGS -I.."
+CPPFLAGS="$CPPFLAGS -I../config"
+CPPFLAGS="$CPPFLAGS -I$SRC/gpf/inc"
+CPPFLAGS="$CPPFLAGS -I$SRC/gpf/frame/cust_os"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/system"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/riviera"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/riviera/rv"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/abb"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/armio"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/clkm"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/conf"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/dma"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/dsp_dwnld"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/inth"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/memif"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/rhea"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/security"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/spi"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/timer"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/uart"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_core/ulpd"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/drivers/drv_app"
+CPPFLAGS="$CPPFLAGS -I$SRC/cs/services"
+
+# Source modules
+
+SRCDIR=$SRC/cs/services/buzm
+
+cfile_plain $SRCDIR/buzm_api.c
+cfile_plain $SRCDIR/buzm_env.c
+cfile_plain $SRCDIR/buzm_handle_message.c
+cfile_plain $SRCDIR/buzm_process.c
+cfile_plain $SRCDIR/buzm_task.c
--- a/configure.sh	Mon Mar 28 00:43:11 2022 +0000
+++ b/configure.sh	Tue Mar 29 03:45:41 2022 +0000
@@ -51,6 +51,7 @@
 DSP=36
 RF=12
 DISABLE_SLEEP=0
+BUZM_STATE=0
 FCHG_STATE=0
 VIBR_STATE=0
 RVTMUX_ON_MODEM=0
@@ -225,7 +226,7 @@
 export CHIPSET DSP RF
 export AMR L1_DYN_DSP_DWNLD L1_VOICE_MEMO_AMR MELODY_E2 SPEECH_RECO
 export DISABLE_SLEEP
-export FCHG_STATE R2D_STATE VIBR_STATE
+export BUZM_STATE FCHG_STATE R2D_STATE VIBR_STATE
 export GPRS MMI SRVC RVTMUX_ON_MODEM
 export R2D_EMBEDDED_LCD UI_CONFIG
 export ALLOW_CSIM_GSM SERIAL_DYNAMIC_SWITCH TR_BAUD_CONFIG
@@ -395,6 +396,10 @@
 # services
 build_lib audio
 build_lib audio_bgd
+if [ "$BUZM_STATE" = 1 ]
+then
+	build_lib buzm
+fi
 build_lib cst
 build_lib dar
 build_lib dar_gbl_var
--- a/scripts/config-headers.sh	Mon Mar 28 00:43:11 2022 +0000
+++ b/scripts/config-headers.sh	Tue Mar 29 03:45:41 2022 +0000
@@ -82,6 +82,12 @@
 fi
 export ATP_STATE
 
+if [ -z "$BUZM_STATE" ]
+then
+	BUZM_STATE=1
+fi
+export BUZM_STATE
+
 if [ -z "$FCHG_STATE" ]
 then
 	FCHG_STATE=1
--- a/scripts/make-rv-swe-hdr.sh	Mon Mar 28 00:43:11 2022 +0000
+++ b/scripts/make-rv-swe-hdr.sh	Tue Mar 29 03:45:41 2022 +0000
@@ -44,6 +44,11 @@
 echo '#define RVM_RTC_SWE'
 echo '#define RVM_FFS_SWE'
 
+if [ "$BUZM_STATE" = 1 ]
+then
+	echo '#define RVM_BUZM_SWE'
+fi
+
 if [ "$VIBR_STATE" = 1 ]
 then
 	echo '#define RVM_VIBR_SWE'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_api.c	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,74 @@
+/*
+ * The implementation of our external API functions lives here.
+ */
+
+#include "buzm/buzm_api.h"
+#include "buzm/buzm_env.h"
+#include "buzm/buzm_messages_i.h"
+#include "rv/rv_general.h"
+#include "rvf/rvf_api.h"
+#include "rvm/rvm_use_id_list.h"
+#include "ffs/ffs_api.h"
+
+T_RV_RET buzm_play_melody(const char *pathname, UINT8 volume, BOOL loop)
+{
+	struct buzm_start_msg *msg;
+	T_FFS_FD fd;
+
+	if (!buzm_env)
+		return RV_NOT_READY;
+	if (volume < BUZM_VOLUME_MIN || volume > BUZM_VOLUME_MAX)
+		return RV_INVALID_PARAMETER;
+	fd = ffs_open(pathname, FFS_O_RDONLY);
+	if (fd <= 0)
+		return RV_INVALID_PARAMETER;
+	if (rvf_get_buf(buzm_env->prim_id, sizeof(struct buzm_start_msg),
+			(T_RVF_BUFFER **)&msg) == RVF_RED) {
+		rvf_send_trace(
+			"rvf_get_buf() failed in buzm_play_melody()", 42,
+			NULL_PARAM, RV_TRACE_LEVEL_ERROR, BUZM_USE_ID);
+		ffs_close(fd);
+		return RV_MEMORY_ERR;
+	}
+	msg->hdr.msg_id        = BUZM_START_REQ;
+	msg->hdr.src_addr_id   = buzm_env->addr_id;
+	msg->hdr.dest_addr_id  = buzm_env->addr_id;
+	msg->hdr.callback_func = NULL;
+	msg->fd = fd;
+	msg->volume = volume;
+	msg->loop = loop;
+	if (rvf_send_msg(buzm_env->addr_id, msg) != RV_OK) {
+		rvf_send_trace("buzm_play_melody(): Send failed!", 32,
+				NULL_PARAM, RV_TRACE_LEVEL_ERROR, BUZM_USE_ID);
+		rvf_free_buf(msg);
+		ffs_close(fd);
+		return RV_INTERNAL_ERR;
+	}
+	return RV_OK;
+}
+
+T_RV_RET buzm_stop_melody(void)
+{
+	struct buzm_stop_msg *msg;
+
+	if (!buzm_env)
+		return RV_NOT_READY;
+	if (rvf_get_buf(buzm_env->prim_id, sizeof(struct buzm_stop_msg),
+			(T_RVF_BUFFER **)&msg) == RVF_RED) {
+		rvf_send_trace(
+			"rvf_get_buf() failed in buzm_stop_melody()", 42,
+			NULL_PARAM, RV_TRACE_LEVEL_ERROR, BUZM_USE_ID);
+		return RV_MEMORY_ERR;
+	}
+	msg->hdr.msg_id        = BUZM_STOP_REQ;
+	msg->hdr.src_addr_id   = buzm_env->addr_id;
+	msg->hdr.dest_addr_id  = buzm_env->addr_id;
+	msg->hdr.callback_func = NULL;
+	if (rvf_send_msg(buzm_env->addr_id, msg) != RV_OK) {
+		rvf_send_trace("buzm_stop_melody(): Send failed!", 32,
+				NULL_PARAM, RV_TRACE_LEVEL_ERROR, BUZM_USE_ID);
+		rvf_free_buf(msg);
+		return RV_INTERNAL_ERR;
+	}
+	return RV_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_api.h	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,17 @@
+/*
+ * This header file defines the external API of our BUZM SWE,
+ * callable from other tasks such as UI or AT commands.
+ */
+
+#ifndef __BUZM_API_H
+#define __BUZM_API_H
+
+#include "rv/rv_general.h"
+
+#define	BUZM_VOLUME_MIN		1
+#define	BUZM_VOLUME_MAX		64
+
+T_RV_RET buzm_play_melody(const char *pathname, UINT8 volume, BOOL loop);
+T_RV_RET buzm_stop_melody(void);
+
+#endif	/* include guard */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_env.c	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,107 @@
+/*
+ * This module provides the glue to the RiViera environment
+ * for our BUZM SWE.
+ */
+
+#include "buzm/buzm_env.h"
+#include "rv/rv_general.h"
+#include "rvf/rvf_api.h"
+#include "rvm/rvm_priorities.h"
+#include "rvm/rvm_api.h"
+#include "rvm/rvm_use_id_list.h"
+#include <string.h>
+
+/* global control block for our SWE */
+struct buzm_env *buzm_env;
+
+/* Define global pointer to the error function */
+static T_RVM_RETURN (*xxx_error_ft) (T_RVM_NAME    swe_name,
+                                     T_RVM_RETURN  error_cause,
+                                     T_RVM_ERROR_TYPE  error_type,
+                                     T_RVM_STRING   error_msg);
+
+T_RVM_RETURN buzm_get_info (T_RVM_INFO_SWE  *infoSWE)
+{
+   /* SWE info */
+
+   infoSWE->swe_type = RVM_SWE_TYPE_4;
+   infoSWE->type_info.type4.swe_use_id = BUZM_USE_ID;
+   memcpy( infoSWE->type_info.type4.swe_name, "BUZM", 5 );
+
+   infoSWE->type_info.type4.stack_size = BUZM_STACK_SIZE;
+   infoSWE->type_info.type4.priority   = RVM_BUZM_TASK_PRIORITY;
+
+   /* memory bank info */
+   infoSWE->type_info.type4.nb_mem_bank = 1;
+
+   memcpy ((UINT8 *) infoSWE->type_info.type4.mem_bank[0].bank_name, "BUZM_PRIM", 10);
+   infoSWE->type_info.type4.mem_bank[0].initial_params.size          = BUZM_MB_PRIM_SIZE;
+   infoSWE->type_info.type4.mem_bank[0].initial_params.watermark     = BUZM_MB_PRIM_WATERMARK;
+
+   /* linked SWE info: we use FFS */
+   infoSWE->type_info.type4.nb_linked_swe    = 1;
+   infoSWE->type_info.type4.linked_swe_id[0] = FFS_USE_ID;
+
+   /* generic functions */
+   infoSWE->type_info.type4.set_info = buzm_set_info;
+   infoSWE->type_info.type4.init     = buzm_init;
+   infoSWE->type_info.type4.core     = buzm_core;
+   infoSWE->type_info.type4.stop     = buzm_stop;
+   infoSWE->type_info.type4.kill     = buzm_kill;
+
+   /* Set the return path */
+   infoSWE->type_info.type4.return_path.callback_func = NULL;
+   infoSWE->type_info.type4.return_path.addr_id	      = 0;
+
+   return RV_OK;
+}
+
+T_RVM_RETURN buzm_set_info(T_RVF_ADDR_ID   addr_id,
+                           T_RV_RETURN     return_path[],
+                           T_RVF_MB_ID     mbId[],
+                           T_RVM_RETURN  (*callBackFct) (T_RVM_NAME SWEntName,
+                                                         T_RVM_RETURN errorCause,
+                                                         T_RVM_ERROR_TYPE errorType,
+                                                         T_RVM_STRING errorMsg))
+{
+
+    T_RVF_MB_STATUS   mb_status;
+
+    mb_status = rvf_get_buf(mbId[0],sizeof(struct buzm_env),(void **) &buzm_env);
+    if (mb_status == RVF_RED) 
+    {
+        rvf_send_trace("buzm_set_info: rvf_get_buf() failed", 35,
+                       NULL_PARAM, RV_TRACE_LEVEL_ERROR, BUZM_USE_ID);
+        return (RVM_MEMORY_ERR);
+    }
+    memset(buzm_env, 0, sizeof(struct buzm_env));
+
+    /* store the pointer to the error function */
+    xxx_error_ft = callBackFct ;
+
+    /* Store the addr id */
+    buzm_env->addr_id = addr_id;
+
+    /* Store the memory bank id */
+    buzm_env->prim_id = mbId[0];
+
+    return RV_OK;
+}
+
+T_RVM_RETURN buzm_init(void)
+{
+   return RV_OK;
+}
+
+T_RVM_RETURN buzm_stop(void)
+{
+   return RV_OK;
+}
+
+T_RVM_RETURN buzm_kill(void)
+{
+   /* free all memory buffer previously allocated */
+   rvf_free_buf ((void *) buzm_env);
+
+   return RV_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_env.h	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,41 @@
+/*
+ * RiViera environment boilerplate header for BUZM SWE
+ */
+
+#ifndef __BUZM_ENV_H__
+#define __BUZM_ENV_H__
+
+#include "rvm/rvm_gen.h"
+#include "buzm/buzm_struct_i.h"
+#include "buzm/buzm_pool_size.h"
+
+#define	BUZM_MAILBOX		RVF_TASK_MBOX_0
+#define	BUZM_TIMER		RVF_TIMER_0
+
+/* memory bank size and watermark */
+#define BUZM_MB_PRIM_SIZE            BUZM_MB1_SIZE
+#define BUZM_MB_PRIM_WATERMARK 	    (BUZM_MB_PRIM_SIZE)
+
+#define BUZM_MB_PRIM_INC_SIZE        0
+#define BUZM_MB_PRIM_INC_WATERMARK   0
+
+extern struct buzm_env *buzm_env;
+
+/* Prototypes */
+
+T_RVM_RETURN buzm_get_info (T_RVM_INFO_SWE  *infoSWE);
+
+T_RVM_RETURN buzm_set_info(T_RVF_ADDR_ID  addr_id,
+                           T_RV_RETURN    return_path[],
+                           T_RVF_MB_ID    mbId[],
+                           T_RVM_RETURN   (*callBackFct) (T_RVM_NAME SWEntName,
+                           T_RVM_RETURN errorCause,
+                           T_RVM_ERROR_TYPE errorType,
+                           T_RVM_STRING errorMsg));
+
+T_RVM_RETURN buzm_init (void);
+T_RVM_RETURN buzm_core (void);
+T_RVM_RETURN buzm_stop (void);
+T_RVM_RETURN buzm_kill (void);
+
+#endif	/* include guard */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_func_i.h	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,15 @@
+/*
+ * Declarations of internal functions live here.
+ */
+
+#ifndef __BUZM_FUNC_I
+#define __BUZM_FUNC_I
+
+#include "buzm/buzm_messages_i.h"
+
+void buzm_process_message(T_RV_HDR *msg_ptr);
+void buzm_process_start_req(struct buzm_start_msg *msg);
+void buzm_process_stop_req(struct buzm_stop_msg *msg);
+void buzm_handle_timer(void);
+
+#endif	/* include guard */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_handle_message.c	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,25 @@
+/*
+ * Incoming message dispatch for our BUZM task is implemented here.
+ */
+
+#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"
+
+void buzm_process_message(T_RV_HDR *msg_ptr)
+{
+	switch (msg_ptr->msg_id) {
+	case BUZM_START_REQ:
+		buzm_process_start_req((struct buzm_start_msg *) msg_ptr);
+		return;
+	case BUZM_STOP_REQ:
+		buzm_process_stop_req((struct buzm_stop_msg *) msg_ptr);
+		return;
+	default:
+		rvf_send_trace("BUZM task: Received an unknown message", 38,
+				NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH,
+				BUZM_USE_ID);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_messages_i.h	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,28 @@
+/*
+ * In this header file we are going to define our internal messages
+ * that will be sent to our BUZM task by our API layer.
+ */
+
+#ifndef __BUZM_MESSAGES_I
+#define __BUZM_MESSAGES_I
+
+#include "rv/rv_general.h"
+#include "ffs/ffs_api.h"
+
+struct buzm_start_msg {
+	T_RV_HDR hdr;
+	T_FFS_FD fd;
+	UINT8 volume;
+	BOOL loop;
+};
+
+struct buzm_stop_msg {
+	T_RV_HDR hdr;
+};
+
+enum buzm_msg_id {
+	BUZM_START_REQ	= 1,
+	BUZM_STOP_REQ
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_pool_size.h	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,13 @@
+/*
+ * Pool size definition required for every RiViera SWE
+ * BUZM is an entirely new FreeCalypso addition
+ */
+
+#ifndef __BUZM_POOL_SIZE_H_
+#define __BUZM_POOL_SIZE_H_
+
+#define BUZM_STACK_SIZE (1024)
+#define BUZM_MB1_SIZE   (2048)
+ 
+#define BUZM_POOL_SIZE  (BUZM_STACK_SIZE + BUZM_MB1_SIZE)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_process.c	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,143 @@
+/*
+ * 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);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_struct_i.h	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,37 @@
+/*
+ * This header file holds the internal structure definition
+ * for BUZM SWE.
+ */
+
+#ifndef __BUZM_STRUCT_I
+#define __BUZM_STRUCT_I
+
+#include "rv/rv_general.h"
+#include "rvf/rvf_api.h"
+#include "ffs/ffs_api.h"
+
+#define	MELODY_CHUNK_SIZE	64	/* entries, not bytes */
+
+struct melody_entry {
+	UINT8	pwt_note;
+	UINT8	note_volume;
+	UINT16	duration;
+};
+
+struct buzm_env {
+	/* RiViera boilerplate */
+	T_RVF_ADDR_ID	addr_id;
+	T_RVF_MB_ID	prim_id;
+	/* global flag */
+	BOOL		melody_running;
+	/* all following vars are valid only during melody play */
+	T_FFS_FD	ffs_fd;
+	UINT8		play_volume;
+	BOOL		loop_mode;
+	struct melody_entry chunk_buf[MELODY_CHUNK_SIZE];
+	UINT8		chunk_play_ptr;
+	UINT8		chunk_end_ptr;
+	BOOL		melody_end_flag;
+};
+
+#endif	/* include guard */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/buzm/buzm_task.c	Tue Mar 29 03:45:41 2022 +0000
@@ -0,0 +1,39 @@
+/*
+ * Our BUZM task's core function lives here.
+ */
+
+#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"
+
+T_RV_RET buzm_core(void)
+{	
+	BOOLEAN error_occured = FALSE;
+	T_RV_HDR *msg_ptr;
+
+	/* loop to process messages */
+	while (error_occured == FALSE)
+	{
+		/* Wait for the necessary events (infinite wait for a msg in the mailbox 0). */
+		UINT16 received_event = rvf_wait (0xffff, 0);
+					
+		/* If an event related to mailbox 0 is received, then */
+		if (received_event & RVF_TASK_MBOX_0_EVT_MASK) 
+		{
+			/* Read the message in the driver mailbox and delegate action..*/
+			msg_ptr = (T_RV_HDR *) rvf_read_mbox(BUZM_MAILBOX);
+			if (msg_ptr) {
+				buzm_process_message(msg_ptr);
+				rvf_free_buf ((void *) msg_ptr);
+			}
+		}
+
+		/* Timers */
+		if (received_event & RVF_TIMER_0_EVT_MASK)
+			buzm_handle_timer();
+
+	}	 // end of while
+	return RV_OK;	
+}
--- a/targets/c11x.conf	Mon Mar 28 00:43:11 2022 +0000
+++ b/targets/c11x.conf	Tue Mar 29 03:45:41 2022 +0000
@@ -2,6 +2,7 @@
 FLASH_BASE_ADDR=0x10000
 FLASH_SECTOR_SIZE=0x10000
 
+BUZM_STATE=1
 FCHG_STATE=1
 VIBR_STATE=1
 RVTMUX_ON_MODEM=1
--- a/targets/c139.conf	Mon Mar 28 00:43:11 2022 +0000
+++ b/targets/c139.conf	Tue Mar 29 03:45:41 2022 +0000
@@ -2,6 +2,7 @@
 FLASH_BASE_ADDR=0x10000
 FLASH_SECTOR_SIZE=0x10000
 
+BUZM_STATE=1
 FCHG_STATE=1
 VIBR_STATE=1
 RVTMUX_ON_MODEM=1