Skip to content

Commit

Permalink
backlight control modified, suspected CPU reset when turned on too ea…
Browse files Browse the repository at this point in the history
…rly (#694)

* Modified backlight, no need to init from splash_hook_handler

SysTick_Handler now "waits" until original firmware turns on the
backlight. Turning BL on too early may have caused CPU reset, when power
supply wasn't fully operational. Details in irq_handlers.c .

* integrated kb_backlight, for manual control from keyb.c

to support enable/disable backlight with sidekey (compatible with #695,
but kb_backlight should be declared as external in keyb.h, and
implemented in keyb.c)

* modified backlight in menu.c as per #697

moved backlight low, high, timer into a submenu as suggested by Mike.
Also modified: Default for high level is '9' now, when no valid default
loaded from flash (before cfg_save). Tested, ok on MD380 / NoGPS.

* added basic Morse code encoder with audio output

uses Timer8 / Channel 3 to generate PWM'ed tones. To test, change the
definition of CONFIG_MORSE_OUTPUT in CONFIG.H .
Leave CONFIG_MORSE_OUTPUT = 0 as long as the Morse output is just a
"demo" (fixed message, cannot read currently selected menu item / string
yet)
  • Loading branch information
Wolf-DL4YHF authored and travisgoodspeed committed Feb 23, 2017
1 parent 5f65c19 commit 05cfb58
Show file tree
Hide file tree
Showing 9 changed files with 916 additions and 257 deletions.
5 changes: 3 additions & 2 deletions applet/config.h
Expand Up @@ -19,8 +19,9 @@
#define CONFIG_DMR
#define CONFIG_MENU
#define CONFIG_AES
#ifndef FW_D02_032 // when trying to compile for 'FW_D02_032', 'backlight_timer' was unknown :(
# define CONFIG_DIMMED_LIGHT 1 // PWMed 'dimmable backlight' ? 0 or undefined = no, 1 = yes
#ifndef FW_D02_032 // Not for very old firmware (missing hooks..):
# define CONFIG_DIMMED_LIGHT 1 // Dimmable backlight ? 0 or undef'd=no, 1=yes
# define CONFIG_MORSE_OUTPUT 0 // Morse output ? 0 or undef'd=no, 1=yes
#endif

/* Uncomment this to print AMBE frames for decoding with DSD. You
Expand Down
863 changes: 724 additions & 139 deletions applet/src/irq_handlers.c

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions applet/src/irq_handlers.h
Expand Up @@ -5,12 +5,12 @@
// for example for the software PWMed 'dimmed backlight'.
// Module prefix : "IRQ_" .

#ifndef CONFIG_DIMMED_LIGHT // want to have a 'dimmed, permanent backlight' ?
# define CONFIG_DIMMED_LIGHT 0 // guess not (otherwise CONFIG_DIMMED_LIGHT would have been defined AS ONE in config.h)
#ifndef CONFIG_DIMMED_LIGHT // want 'dimmable backlight' ?
# define CONFIG_DIMMED_LIGHT 0 // guess not (else set CONFIG_DIMMED_LIGHT=1 in config.h)
#endif

#ifndef BYTE
# define BYTE uint8_t /* formerly kown as 'unsigned char' (for stoneage C compilers). 'uint8_t' was unknwon here. */
#ifndef CONFIG_MORSE_OUTPUT // want output in Morse code ?
# define CONFIG_MORSE_OUTPUT 0 // guess not (else set CONFIG_MORSE_OUTPUT=1 in config.h)
#endif

// Offsets into the STM32's vector table. These may be defined somewhere else, but WB didn't find anything like this.
Expand Down Expand Up @@ -44,6 +44,8 @@
extern uint8_t GFX_backlight_on; // 0="off" (low intensity), 1="on" (high intensity)
// (note: GFX_backlight_on is useless, as long as no-one calls gfx.c :

void IRQ_Init(void); // details in the implementaion ( irq_handlers.c )

extern uint8_t kb_backlight; // flag to disable the backlight via sidekey (in keyb.c)

#if( CONFIG_MORSE_OUTPUT )
int MorseGen_AppendString( char *pszText, int iMaxLen ); // API to send 8-bit strings in Morse code
#endif // CONFIG_MORSE_OUTPUT ?
11 changes: 10 additions & 1 deletion applet/src/keyb.c
Expand Up @@ -22,6 +22,11 @@

#include <stdint.h>

uint8_t kb_backlight=0; // flag to disable backlight via sidekey.
// Other keyboard-related variables belong to the original firmware,
// e.g. kb_keypressed, address defined in symbols_d13.020 (etc).


// Values for kp
// 1 = pressed
// 2 = release within timeout
Expand Down Expand Up @@ -194,7 +199,11 @@ void evaluate_sidekey ( int button_function) //This is where new functions
switch ( button_function ) { //We will start at 0x50 to avoid conflicting with any added functions by Tytera.
case 0x50 : //Toggle backlight enable pin to input/output. Disables backlight completely.
{
GPIOC->MODER = GPIOC->MODER ^ (((uint32_t)0x01) << 12);
#if (CONFIG_DIMMED_LIGHT) // If backlight dimmer is enabled, we will use that instead.
kb_backlight ^= 0x01; // flag for SysTick_Handler() to turn backlight off completely
#else
GPIOC->MODER = GPIOC->MODER ^ (((uint32_t)0x01) << 12);
#endif
reset_backlight();
break;
}
Expand Down
2 changes: 2 additions & 0 deletions applet/src/keyb.h
Expand Up @@ -15,6 +15,8 @@ extern "C" {

void f_4101();

extern uint8_t kb_backlight; // flag to disable backlight via sidekey

#if defined(FW_D13_020) || defined(FW_S13_020)
extern uint8_t kb_keycode;
extern uint8_t kb_keypressed;
Expand Down
8 changes: 0 additions & 8 deletions applet/src/main.c
Expand Up @@ -142,11 +142,6 @@ void boot_splash_set_bottomline(void)

void splash_hook_handler(void)
{

IRQ_Init(); // Prepare everything that may be used in SysTick_Handler(),
// including the optional dimmable backlight (and future interrupt handlers) .
// Note: splash_hook_handler() was *not* called with 'Menu'..'Utilities'
// 'Radio Settings'..'Intro Screen' set to 'Picture', not 'Char String' !

if( global_addl_config.boot_demo == 0 ) {
demo();
Expand Down Expand Up @@ -175,9 +170,6 @@ void splash_hook_handler(void)
*/
int main(void) {

// Too early to call IRQ_Init() here, because Tytera's own init function
// seems to perform a 'reset' (via RCC) on most on-chip peripherals !

dmesg_init();

/*
Expand Down
201 changes: 107 additions & 94 deletions applet/src/menu.c
Expand Up @@ -62,13 +62,13 @@ const static wchar_t wt_blunchanged[] = L"Unchanged";
const static wchar_t wt_bl5[] = L"5 sec";
const static wchar_t wt_bl30[] = L"30 sec";
const static wchar_t wt_bl60[] = L"60 sec";

const static wchar_t wt_backlight_menu[] = L"Backlight";
#ifndef CONFIG_DIMMED_LIGHT // want 'dimmed backlight', two adjustable intensities ?
# define CONFIG_DIMMED_LIGHT 0 // guess not (unless defined AS ONE in config.h)
#endif
#if( CONFIG_DIMMED_LIGHT ) // support pulse-width modulated backlight ?
const static wchar_t wt_bl_intensity_lo[] = L"Backlt Low";
const static wchar_t wt_bl_intensity_hi[] = L"Backlt High";
const static wchar_t wt_bl_intensity_lo[] = L"Level Low";
const static wchar_t wt_bl_intensity_hi[] = L"Level High";
#define NUM_BACKLIGHT_INTENSITIES 10 /* number of intensity steps (0..9) for the menu */
const static wchar_t *wt_bl_intensity[NUM_BACKLIGHT_INTENSITIES] =
{ L"0 (off)", L"1 (lowest)", L"2", L"3 (medium)", L"4",
Expand Down Expand Up @@ -117,8 +117,8 @@ const static wchar_t wt_button_lone_work[] = L"Lone wk On/Off";
const static wchar_t wt_button_1750_hz[] = L"1750hz Tone";
const static wchar_t wt_button_bklt_en[] = L"Toggle bklight";
const static uint8_t button_functions[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1e,
0x1f, 0x26, 0x50};
0x0b, 0x0c, 0x0d, 0x0e, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1e,
0x1f, 0x26, 0x50};
uint8_t button_selected = 0;
uint8_t button_function = 0;

Expand Down Expand Up @@ -250,8 +250,8 @@ uint8_t index_of(uint8_t value, uint8_t arr[], uint8_t len)
uint8_t i = 0;
while(i < len)
{
if (arr[i] == value) return i;
i++;
if (arr[i] == value) return i;
i++;
}

return 0;
Expand Down Expand Up @@ -910,8 +910,11 @@ void mn_backlight_intens( int intensity ) // common 'menu handler' for all <NUM_
global_addl_config.backlight_intensities |= ((uint8_t)intensity << 4);
break;
}
// the upper 4 bits must never be ZERO, to avoid 'complete darkness' of the display when ACTIVE :
global_addl_config.backlight_intensities |= 0x10;
// The upper 4 bits must never be ZERO, to avoid 'complete darkness' of the display when ACTIVE .
// Because in some radios, the PWM caused audible hum, use max brightness per default:
if( !(global_addl_config.backlight_intensities & 0xF0) )
{ global_addl_config.backlight_intensities |= 0xF0;
}
cfg_save();

} // end mn_backlight_intens()
Expand Down Expand Up @@ -975,83 +978,83 @@ void mn_backlight_hi(void) // configure HIGH backlight intensity (used when "ac
#if defined(FW_D13_020) || defined(FW_S13_020)
void set_sidebutton_function(void)
{
button_function = button_functions[currently_selected_menu_entry];

switch ( button_selected ) {
case 0:
top_side_button_pressed_function = button_function;
md380_spiflash_write(&button_function, 0x2102, 1);
mn_create_single_timed_ack(wt_button_top_press,wt_button_func_set);
break;
case 1:
bottom_side_button_pressed_function = button_function;
md380_spiflash_write(&button_function, 0x2104, 1);
mn_create_single_timed_ack(wt_button_bot_press,wt_button_func_set);
break;
case 2:
top_side_button_held_function = button_function;
md380_spiflash_write(&button_function, 0x2103, 1);
mn_create_single_timed_ack(wt_button_top_held,wt_button_func_set);
break;
case 3:
bottom_side_button_held_function = button_function;
md380_spiflash_write(&button_function, 0x2105, 1);
mn_create_single_timed_ack(wt_button_bot_held,wt_button_func_set);
break;
}
button_function = button_functions[currently_selected_menu_entry];

switch ( button_selected ) {
case 0:
top_side_button_pressed_function = button_function;
md380_spiflash_write(&button_function, 0x2102, 1);
mn_create_single_timed_ack(wt_button_top_press,wt_button_func_set);
break;
case 1:
bottom_side_button_pressed_function = button_function;
md380_spiflash_write(&button_function, 0x2104, 1);
mn_create_single_timed_ack(wt_button_bot_press,wt_button_func_set);
break;
case 2:
top_side_button_held_function = button_function;
md380_spiflash_write(&button_function, 0x2103, 1);
mn_create_single_timed_ack(wt_button_top_held,wt_button_func_set);
break;
case 3:
bottom_side_button_held_function = button_function;
md380_spiflash_write(&button_function, 0x2105, 1);
mn_create_single_timed_ack(wt_button_bot_held,wt_button_func_set);
break;
}
}

void select_sidebutton_function_screen(void)
{
button_selected = currently_selected_menu_entry;

switch ( button_selected ) {
case 0:
md380_menu_entry_selected = index_of(top_side_button_pressed_function, button_functions, sizeof(button_functions));
mn_submenu_init(wt_button_top_press);
break;
case 1:
md380_menu_entry_selected = index_of(bottom_side_button_pressed_function, button_functions, sizeof(button_functions));
mn_submenu_init(wt_button_bot_press);
break;
case 2:
md380_menu_entry_selected = index_of(top_side_button_held_function, button_functions, sizeof(button_functions));
mn_submenu_init(wt_button_top_held);
break;
case 3:
md380_menu_entry_selected = index_of(bottom_side_button_held_function, button_functions, sizeof(button_functions));
mn_submenu_init(wt_button_bot_held);
break;
}


mn_submenu_add(wt_button_unassigned, set_sidebutton_function);
mn_submenu_add(wt_button_alert_tone, set_sidebutton_function);
mn_submenu_add(wt_button_emerg_on, set_sidebutton_function);
mn_submenu_add(wt_button_emerg_off, set_sidebutton_function);
mn_submenu_add(wt_button_power, set_sidebutton_function);
mn_submenu_add(wt_button_monitor, set_sidebutton_function);
mn_submenu_add(wt_button_nuisance, set_sidebutton_function);
mn_submenu_add(wt_button_ot1, set_sidebutton_function);
mn_submenu_add(wt_button_ot2, set_sidebutton_function);
mn_submenu_add(wt_button_ot3, set_sidebutton_function);
mn_submenu_add(wt_button_ot4, set_sidebutton_function);
mn_submenu_add(wt_button_ot5, set_sidebutton_function);
mn_submenu_add(wt_button_ot6, set_sidebutton_function);
mn_submenu_add(wt_button_rep_talk, set_sidebutton_function);
mn_submenu_add(wt_button_scan, set_sidebutton_function);
mn_submenu_add(wt_button_squelch, set_sidebutton_function);
mn_submenu_add(wt_button_privacy, set_sidebutton_function);
mn_submenu_add(wt_button_vox, set_sidebutton_function);
mn_submenu_add(wt_button_zone, set_sidebutton_function);
mn_submenu_add(wt_button_zone_tog, set_sidebutton_function);
mn_submenu_add(wt_button_bat_ind, set_sidebutton_function);
mn_submenu_add(wt_button_man_dial, set_sidebutton_function);
mn_submenu_add(wt_button_lone_work, set_sidebutton_function);
mn_submenu_add(wt_button_1750_hz, set_sidebutton_function);
mn_submenu_add(wt_button_bklt_en, set_sidebutton_function);

mn_submenu_finalize();
button_selected = currently_selected_menu_entry;

switch ( button_selected ) {
case 0:
md380_menu_entry_selected = index_of(top_side_button_pressed_function, button_functions, sizeof(button_functions));
mn_submenu_init(wt_button_top_press);
break;
case 1:
md380_menu_entry_selected = index_of(bottom_side_button_pressed_function, button_functions, sizeof(button_functions));
mn_submenu_init(wt_button_bot_press);
break;
case 2:
md380_menu_entry_selected = index_of(top_side_button_held_function, button_functions, sizeof(button_functions));
mn_submenu_init(wt_button_top_held);
break;
case 3:
md380_menu_entry_selected = index_of(bottom_side_button_held_function, button_functions, sizeof(button_functions));
mn_submenu_init(wt_button_bot_held);
break;
}


mn_submenu_add(wt_button_unassigned, set_sidebutton_function);
mn_submenu_add(wt_button_alert_tone, set_sidebutton_function);
mn_submenu_add(wt_button_emerg_on, set_sidebutton_function);
mn_submenu_add(wt_button_emerg_off, set_sidebutton_function);
mn_submenu_add(wt_button_power, set_sidebutton_function);
mn_submenu_add(wt_button_monitor, set_sidebutton_function);
mn_submenu_add(wt_button_nuisance, set_sidebutton_function);
mn_submenu_add(wt_button_ot1, set_sidebutton_function);
mn_submenu_add(wt_button_ot2, set_sidebutton_function);
mn_submenu_add(wt_button_ot3, set_sidebutton_function);
mn_submenu_add(wt_button_ot4, set_sidebutton_function);
mn_submenu_add(wt_button_ot5, set_sidebutton_function);
mn_submenu_add(wt_button_ot6, set_sidebutton_function);
mn_submenu_add(wt_button_rep_talk, set_sidebutton_function);
mn_submenu_add(wt_button_scan, set_sidebutton_function);
mn_submenu_add(wt_button_squelch, set_sidebutton_function);
mn_submenu_add(wt_button_privacy, set_sidebutton_function);
mn_submenu_add(wt_button_vox, set_sidebutton_function);
mn_submenu_add(wt_button_zone, set_sidebutton_function);
mn_submenu_add(wt_button_zone_tog, set_sidebutton_function);
mn_submenu_add(wt_button_bat_ind, set_sidebutton_function);
mn_submenu_add(wt_button_man_dial, set_sidebutton_function);
mn_submenu_add(wt_button_lone_work, set_sidebutton_function);
mn_submenu_add(wt_button_1750_hz, set_sidebutton_function);
mn_submenu_add(wt_button_bklt_en, set_sidebutton_function);

mn_submenu_finalize();
}
#else
#warning Side Buttons not supported on D02 firmware
Expand All @@ -1061,7 +1064,7 @@ void create_menu_entry_sidebutton_screen(void)
{
#if defined(FW_D13_020) || defined(FW_S13_020)

md380_menu_entry_selected = 0;
md380_menu_entry_selected = 0;
mn_submenu_init(wt_sidebutton_menu);

mn_submenu_add_98(wt_button_top_press, select_sidebutton_function_screen);
Expand All @@ -1073,6 +1076,21 @@ void create_menu_entry_sidebutton_screen(void)
#endif
}

void create_menu_entry_backlight_screen(void)
{
#if defined(FW_D13_020) || defined(FW_S13_020)
md380_menu_entry_selected = 0;
mn_submenu_init(wt_backlight_menu);

# if( CONFIG_DIMMED_LIGHT ) // *optional* feature since 2017-01-08 - see config.h
mn_submenu_add_98(wt_bl_intensity_lo/*item text*/, mn_backlight_lo/*menu handler*/ ); // backlight intensity "low" (used when idle)
mn_submenu_add_98(wt_bl_intensity_hi/*item text*/, mn_backlight_hi/*menu handler*/ ); // backlight intensity "high" (used when active)
# endif
mn_submenu_add_98(wt_backlight, mn_backlight); // backlight TIMER (longer than Tytera's 5/10/15 seconds)
mn_submenu_finalize2();
#endif
}


void mn_config_reset2()
{
Expand Down Expand Up @@ -1281,13 +1299,8 @@ void create_menu_entry_addl_functions_screen(void)

mn_submenu_add_98(wt_config_reset, mn_config_reset);

# if( CONFIG_DIMMED_LIGHT ) // *optional* feature since 2017-01-08 - see config.h
mn_submenu_add_98(wt_bl_intensity_lo/*item text*/, mn_backlight_lo/*menu handler*/ ); // backlight intensity "low" (used when idle)
mn_submenu_add_98(wt_bl_intensity_hi/*item text*/, mn_backlight_hi/*menu handler*/ ); // backlight intensity "high" (used when active)
# endif

mn_submenu_add_98(wt_backlight, mn_backlight); // backlight TIMER (longer than Tytera's 5/10/15 seconds)

mn_submenu_add(wt_backlight_menu, create_menu_entry_backlight_screen);

mn_submenu_add_98(wt_cp_override, mn_cp_override);
mn_submenu_add_98(wt_netmon, create_menu_entry_netmon_screen);

Expand Down Expand Up @@ -1350,11 +1363,11 @@ void *main_menu_hook(void *menu){
menustruct=(void*) *((int*)menu + 2);

printf("Menu struct: @0x%08x\n",
menustruct);
menustruct);
printf("Item %5d/%5d selected. %s\n",
(int) *((unsigned short*) (menustruct+0x42)),
(int) *((unsigned short*)menustruct),
"test");
(int) *((unsigned short*) (menustruct+0x42)),
(int) *((unsigned short*)menustruct),
"test");


//printhex(*((int*) menu+2),128);
Expand Down
9 changes: 9 additions & 0 deletions delete_object_files_and_listings.bat
@@ -0,0 +1,9 @@
REM clear OBJECT FILES but not MAP-, BIN-, and IMG files
del applet\*.o
del applet\*.lst
del applet\lib\*.o
del applet\lib\*.lst
del annotations\d13.020\listing.txt
REM on this occasion, also delete 'compiled' python modules
del *.pyc
pause

0 comments on commit 05cfb58

Please sign in to comment.