/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2004 Mike Holden * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "plugin.h" PLUGIN_HEADER #ifdef HAVE_LCD_BITMAP #define TIMER_Y 1 #else #define TIMER_Y 0 #endif #define LAP_Y TIMER_Y+1 #define MAX_LAPS 64 /* variable button definitions */ #if CONFIG_KEYPAD == RECORDER_PAD #define STOPWATCH_QUIT BUTTON_OFF #define STOPWATCH_START_STOP BUTTON_PLAY #define STOPWATCH_RESET_TIMER BUTTON_LEFT #define STOPWATCH_LAP_TIMER BUTTON_ON #define STOPWATCH_SCROLL_UP BUTTON_UP #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD #define STOPWATCH_QUIT BUTTON_OFF #define STOPWATCH_START_STOP BUTTON_SELECT #define STOPWATCH_RESET_TIMER BUTTON_LEFT #define STOPWATCH_LAP_TIMER BUTTON_ON #define STOPWATCH_SCROLL_UP BUTTON_UP #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == ONDIO_PAD #define STOPWATCH_QUIT BUTTON_OFF #define STOPWATCH_START_STOP BUTTON_RIGHT #define STOPWATCH_RESET_TIMER BUTTON_LEFT #define STOPWATCH_LAP_TIMER BUTTON_MENU #define STOPWATCH_SCROLL_UP BUTTON_UP #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == PLAYER_PAD #define STOPWATCH_QUIT BUTTON_MENU #define STOPWATCH_START_STOP BUTTON_PLAY #define STOPWATCH_RESET_TIMER BUTTON_STOP #define STOPWATCH_LAP_TIMER BUTTON_ON #define STOPWATCH_SCROLL_UP BUTTON_RIGHT #define STOPWATCH_SCROLL_DOWN BUTTON_LEFT #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ (CONFIG_KEYPAD == IRIVER_H300_PAD) #define STOPWATCH_QUIT BUTTON_OFF #define STOPWATCH_START_STOP BUTTON_SELECT #define STOPWATCH_RESET_TIMER BUTTON_DOWN #define STOPWATCH_LAP_TIMER BUTTON_ON #define STOPWATCH_SCROLL_UP BUTTON_RIGHT #define STOPWATCH_SCROLL_DOWN BUTTON_LEFT #define STOPWATCH_RC_QUIT BUTTON_RC_STOP #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == IPOD_3G_PAD) || \ (CONFIG_KEYPAD == IPOD_1G2G_PAD) #define STOPWATCH_QUIT BUTTON_MENU #define STOPWATCH_START_STOP BUTTON_SELECT #define STOPWATCH_RESET_TIMER BUTTON_LEFT #define STOPWATCH_LAP_TIMER BUTTON_RIGHT #define STOPWATCH_SCROLL_UP BUTTON_SCROLL_FWD #define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_BACK #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD #define STOPWATCH_QUIT BUTTON_PLAY #define STOPWATCH_START_STOP BUTTON_MODE #define STOPWATCH_RESET_TIMER BUTTON_EQ #define STOPWATCH_LAP_TIMER BUTTON_SELECT #define STOPWATCH_SCROLL_UP BUTTON_UP #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD #define STOPWATCH_QUIT BUTTON_POWER #define STOPWATCH_START_STOP BUTTON_PLAY #define STOPWATCH_RESET_TIMER BUTTON_REC #define STOPWATCH_LAP_TIMER BUTTON_SELECT #define STOPWATCH_SCROLL_UP BUTTON_UP #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == GIGABEAT_PAD #define STOPWATCH_QUIT BUTTON_POWER #define STOPWATCH_START_STOP BUTTON_SELECT #define STOPWATCH_RESET_TIMER BUTTON_A #define STOPWATCH_LAP_TIMER BUTTON_MENU #define STOPWATCH_SCROLL_UP BUTTON_UP #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == SANSA_E200_PAD #define STOPWATCH_QUIT BUTTON_POWER #define STOPWATCH_START_STOP BUTTON_LEFT #define STOPWATCH_RESET_TIMER BUTTON_REC #define STOPWATCH_LAP_TIMER BUTTON_SELECT #define STOPWATCH_SCROLL_UP BUTTON_UP #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN #elif CONFIG_KEYPAD == IRIVER_H10_PAD #define STOPWATCH_QUIT BUTTON_POWER #define STOPWATCH_START_STOP BUTTON_PLAY #define STOPWATCH_RESET_TIMER BUTTON_REW #define STOPWATCH_LAP_TIMER BUTTON_FF #define STOPWATCH_SCROLL_UP BUTTON_SCROLL_UP #define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_DOWN #endif static struct plugin_api* rb; static int stopwatch = 0; static long start_at = 0; static int prev_total = 0; static bool counting = false; static int curr_lap = 0; static int lap_scroll = 0; static int lap_start; static int lap_times[MAX_LAPS]; static void ticks_to_string(int ticks,int lap,int buflen, char * buf) { int hours, minutes, seconds, cs; hours = ticks / (HZ * 3600); ticks -= (HZ * hours * 3600); minutes = ticks / (HZ * 60); ticks -= (HZ * minutes * 60); seconds = ticks / HZ; ticks -= (HZ * seconds); cs = ticks; if (!lap) { rb->snprintf(buf, buflen, "%2d:%02d:%02d.%02d", hours, minutes, seconds, cs); } else { if (lap > 1) { int last_ticks, last_hours, last_minutes, last_seconds, last_cs; last_ticks = lap_times[(lap-1)%MAX_LAPS] - lap_times[(lap-2)%MAX_LAPS]; last_hours = last_ticks / (HZ * 3600); last_ticks -= (HZ * last_hours * 3600); last_minutes = last_ticks / (HZ * 60); last_ticks -= (HZ * last_minutes * 60); last_seconds = last_ticks / HZ; last_ticks -= (HZ * last_seconds); last_cs = last_ticks; rb->snprintf(buf, buflen, "%2d %2d:%02d:%02d.%02d [%2d:%02d:%02d.%02d]", lap, hours, minutes, seconds, cs, last_hours, last_minutes, last_seconds, last_cs); } else { rb->snprintf(buf, buflen, "%2d %2d:%02d:%02d.%02d", lap, hours, minutes, seconds, cs); } } } enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { char buf[32]; int button; int lap; int done = false; bool update_lap = true; int lines; (void)parameter; rb = api; #ifdef HAVE_LCD_BITMAP int h; rb->lcd_setfont(FONT_UI); rb->lcd_getstringsize("M", NULL, &h); lines = (LCD_HEIGHT / h) - (LAP_Y); #else lines = 1; #endif rb->lcd_clear_display(); while (!done) { if (counting) { stopwatch = prev_total + *rb->current_tick - start_at; } else { stopwatch = prev_total; } ticks_to_string(stopwatch,0,32,buf); rb->lcd_puts(0, TIMER_Y, buf); if(update_lap) { lap_start = curr_lap - lap_scroll; for (lap = lap_start; lap > lap_start - lines; lap--) { if (lap > 0) { ticks_to_string(lap_times[(lap-1)%MAX_LAPS],lap,32,buf); rb->lcd_puts_scroll(0, LAP_Y + lap_start - lap, buf); } else { rb->lcd_puts(0, LAP_Y + lap_start - lap, " "); } } update_lap = false; } rb->lcd_update(); if (! counting) { button = rb->button_get(true); } else { button = rb->button_get_w_tmo(10); /* Make sure that the jukebox isn't powered off automatically */ rb->reset_poweroff_timer(); } switch (button) { /* exit */ #ifdef STOPWATCH_RC_QUIT case STOPWATCH_RC_QUIT: #endif case STOPWATCH_QUIT: done = true; break; /* Stop/Start toggle */ case STOPWATCH_START_STOP: counting = ! counting; if (counting) { start_at = *rb->current_tick; stopwatch = prev_total + *rb->current_tick - start_at; } else { prev_total += *rb->current_tick - start_at; stopwatch = prev_total; } break; /* Reset timer */ case STOPWATCH_RESET_TIMER: if (!counting) { prev_total = 0; curr_lap = 0; update_lap = true; } break; /* Lap timer */ case STOPWATCH_LAP_TIMER: lap_times[curr_lap%MAX_LAPS] = stopwatch; curr_lap++; update_lap = true; break; /* Scroll Lap timer up */ case STOPWATCH_SCROLL_UP: if (lap_scroll > 0) { lap_scroll --; update_lap = true; } break; /* Scroll Lap timer down */ case STOPWATCH_SCROLL_DOWN: if ((lap_scroll < curr_lap - lines) && (lap_scroll < (MAX_LAPS - lines)) ) { lap_scroll ++; update_lap = true; } break; default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) return PLUGIN_USB_CONNECTED; break; } } return PLUGIN_OK; } ef='#n199'>199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
 *                                                                  *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
 *                                                                  *
 ********************************************************************

 function: miscellaneous math and prototypes

 ********************************************************************/

//#include "config-tremor.h"

#ifndef _V_RANDOM_H_
#define _V_RANDOM_H_
//#include "ivorbiscodec.h"
//#include "os_types.h"

//#include "asm_arm.h"
//#include "asm_mcf5249.h"


/* Some prototypes that were not defined elsewhere */
//void *_vorbis_block_alloc(vorbis_block *vb,long bytes);
//void _vorbis_block_ripcord(vorbis_block *vb);
//extern int _ilog(unsigned int v);

#ifndef _V_WIDE_MATH
#define _V_WIDE_MATH

#ifndef ROCKBOX
#include <inttypes.h>
#endif /* ROCKBOX */

#ifndef  _LOW_ACCURACY_
/* 64 bit multiply */
/* #include <sys/types.h> */

#if ROCKBOX_LITTLE_ENDIAN == 1
union magic {
  struct {
    int32_t lo;
    int32_t hi;
  } halves;
  int64_t whole;
};
#elif ROCKBOX_BIG_ENDIAN == 1
union magic {
  struct {
    int32_t hi;
    int32_t lo;
  } halves;
  int64_t whole;
};
#endif

static inline int32_t MULT32(int32_t x, int32_t y) {
  union magic magic;
  magic.whole = (int64_t)x * y;
  return magic.halves.hi;
}
static inline int32_t MULT31(int32_t x, int32_t y) {
  return MULT32(x,y)<<1;
}

static inline int32_t MULT31_SHIFT15(int32_t x, int32_t y) {
  union magic magic;
  magic.whole  = (int64_t)x * y;
  return ((uint32_t)(magic.halves.lo)>>15) | ((magic.halves.hi)<<17);
}

#else
/* 32 bit multiply, more portable but less accurate */

/*
 * Note: Precision is biased towards the first argument therefore ordering
 * is important.  Shift values were chosen for the best sound quality after
 * many listening tests.
 */

/*
 * For MULT32 and MULT31: The second argument is always a lookup table
 * value already preshifted from 31 to 8 bits.  We therefore take the
 * opportunity to save on text space and use unsigned char for those
 * tables in this case.
 */

static inline int32_t MULT32(int32_t x, int32_t y) {
  return (x >> 9) * y;  /* y preshifted >>23 */
}

static inline int32_t MULT31(int32_t x, int32_t y) {
  return (x >> 8) * y;  /* y preshifted >>23 */
}

static inline int32_t MULT31_SHIFT15(int32_t x, int32_t y) {
  return (x >> 6) * y;  /* y preshifted >>9 */
}
#endif

/*
 * The XPROD functions are meant to optimize the cross products found all
 * over the place in mdct.c by forcing memory operation ordering to avoid
 * unnecessary register reloads as soon as memory is being written to.
 * However this is only beneficial on CPUs with a sane number of general
 * purpose registers which exclude the Intel x86.  On Intel, better let the
 * compiler actually reload registers directly from original memory by using
 * macros.
 */

/* replaced XPROD32 with a macro to avoid memory reference
   _x, _y are the results (must be l-values) */
#define XPROD32(_a, _b, _t, _v, _x, _y)		\
  { (_x)=MULT32(_a,_t)+MULT32(_b,_v);		\
    (_y)=MULT32(_b,_t)-MULT32(_a,_v); }


#ifdef __i386__

#define XPROD31(_a, _b, _t, _v, _x, _y)		\
  { *(_x)=MULT31(_a,_t)+MULT31(_b,_v);		\
    *(_y)=MULT31(_b,_t)-MULT31(_a,_v); }
#define XNPROD31(_a, _b, _t, _v, _x, _y)	\
  { *(_x)=MULT31(_a,_t)-MULT31(_b,_v);		\
    *(_y)=MULT31(_b,_t)+MULT31(_a,_v); }

#else

static inline void XPROD31(int32_t  a, int32_t  b,
			   int32_t  t, int32_t  v,
			   int32_t *x, int32_t *y)
{
  *x = MULT31(a, t) + MULT31(b, v);
  *y = MULT31(b, t) - MULT31(a, v);
}

static inline void XNPROD31(int32_t  a, int32_t  b,
			    int32_t  t, int32_t  v,
			    int32_t *x, int32_t *y)
{
  *x = MULT31(a, t) - MULT31(b, v);
  *y = MULT31(b, t) + MULT31(a, v);
}
#endif

#ifndef _V_VECT_OPS
#define _V_VECT_OPS

static inline
void vect_add(int32_t *x, int32_t *y, int n)
{
  while (n>0) {
    *x++ += *y++;
    n--;
  }
}

static inline
void vect_copy(int32_t *x, int32_t *y, int n)
{
  while (n>0) {
    *x++ = *y++;
    n--;
  }
}

static inline
void vect_mult_fw(int32_t *data, int32_t *window, int n)
{
  while(n>0) {
    *data = MULT31(*data, *window);
    data++;
    window++;
    n--;
  }
}

static inline
void vect_mult_bw(int32_t *data, int32_t *window, int n)
{
  while(n>0) {
    *data = MULT31(*data, *window);
    data++;
    window--;
    n--;
  }
}
#endif

#endif

#ifndef _V_CLIP_MATH
#define _V_CLIP_MATH

static inline int32_t CLIP_TO_15(int32_t x) {
  int ret=x;
  ret-= ((x<=32767)-1)&(x-32767);
  ret-= ((x>=-32768)-1)&(x+32768);
  return(ret);
}

#endif

static inline int32_t VFLOAT_MULT(int32_t a,int32_t ap,
				      int32_t b,int32_t bp,
				      int32_t *p){
  if(a && b){
#ifndef _LOW_ACCURACY_
    *p=ap+bp+32;
    return MULT32(a,b);
#else
    *p=ap+bp+31;
    return (a>>15)*(b>>16);
#endif
  }else
    return 0;
}

/*static inline int32_t VFLOAT_MULTI(int32_t a,int32_t ap,
				      int32_t i,
				      int32_t *p){

  int ip=_ilog(abs(i))-31;
  return VFLOAT_MULT(a,ap,i<<-ip,ip,p);
}
*/
static inline int32_t VFLOAT_ADD(int32_t a,int32_t ap,
				      int32_t b,int32_t bp,
				      int32_t *p){

  if(!a){
    *p=bp;
    return b;
  }else if(!b){
    *p=ap;
    return a;
  }

  /* yes, this can leak a bit. */
  if(ap>bp){
    int shift=ap-bp+1;
    *p=ap+1;
    a>>=1;
    if(shift<32){
      b=(b+(1<<(shift-1)))>>shift;
    }else{
      b=0;
    }
  }else{
    int shift=bp-ap+1;
    *p=bp+1;
    b>>=1;
    if(shift<32){
      a=(a+(1<<(shift-1)))>>shift;
    }else{
      a=0;
    }
  }

  a+=b;
  if((a&0xc0000000)==0xc0000000 ||
     (a&0xc0000000)==0){
    a<<=1;
    (*p)--;
  }
  return(a);
}

#ifdef __GNUC__
#if __GNUC__ >= 3
#define EXPECT(a, b) __builtin_expect((a), (b))
#else
#define EXPECT(a, b) (a)
#endif
#else
#define EXPECT(a, b) (a)
#endif

#endif