/* Copyright 1996, ESS Technology, Inc. */
/* SCCSID @(#)huffman.c 4.1 11/05/02 */
/*
* $Log$
*/
#include "mvd.h"
#include "common.h"
#include "debug.h"
#include "huffman.h"
#include "const.h"
#include "vp.h"
#define PRINTF(a)
/****************************************************************************
*
* Huffman decoder initialisation.
*
*****************************************************************************/
void HUFF_init(void)
{
int i, table_size;
long *high_table;
high_table = T_huffman_high_table;
mvd[huffdec_control] = 0x23; /* reset & load high-level tbl */
/* Load high-level table */
table_size = T_huffman_high_table_SZ >> 2;
assert(table_size <= 64);
for (i = 0; i < table_size; i++) {
mvd[huffdec_highsram+i] = high_table[i];
}
/* Verify table */
for (i = 0; i < table_size; i++) {
int val;
val = mvd[huffdec_highsram+i] & 0xfffff;
if (val != high_table[i]) {
EPRINTF(("ERR: hd hsram_table fnd: %lx exp:%lx a:%x\n",
val, high_table[i], i));
}
}
HUFF_reset_output_fifo_and_state();
PRINTF(("Done Huffman initialisation\n"));
}
/****************************************************************************
*
* Reset huffman decoder. Used in emergency_save.
*
*****************************************************************************/
void HUFF_reset_output_fifo_and_state()
{
int i;
volatile int stat;
mvd[huffdec_control] = 0x4ac0| HUFRESET;
mvd[huffdec_cmdblock] = HUFFDEC_CMDBLOCK_JNU; /* set cmd block to idle */
asm("nop");
mvd[huffdec_control] = 0x4ac0;
stat = mvd[huffdec_stat2] & 0xff;
stat = stat || stat<<8;
mvd[0xb01c/4] = stat; /*To init r1,r2, work with both old and new compiler*/
mvd[huffdec_ldinc_addr] = 0x1dc; /* for MPEG1 */
mvd[huffdec_packet_counter] = 0x100;
mvd[huffdec_cmdblock] = HUFFDEC_CMDBLOCK_MBA_ADDR;
}
/****************************************************************************
*
* Reset huffman decoder, DO not reset INPUT fifo. Used in emergency_save.
*
*****************************************************************************/
#define VPSTAT_DH 0x2000
void HUFF_reset_state_machine()
{
int i;
mvd[huffdec_control] = 0x4ac0| HUFDECRESET;
mvd[huffdec_cmdblock] = HUFFDEC_CMDBLOCK_JNU; /* set cmd block to idle */
VP_cmdq_reset(0);
/* clean up the NRLA fifo */
do {
i = mvd[huffdec_nrlarisc];
} while (mvd[huffdec_stat1] & 0x3f);
/* clean up the RLA fifo */
do {
VP_block(0,VPSTAT_DH);
risc_sleep_a_bit(100);
} while (mvd[huffdec_stat1] & 0x3c0);
VP_cmdq_reset(0);
mvd[huffdec_control] = 0x4ac0;
mvd[huffdec_ldinc_addr] = 0x1dc; /* for MPEG1 */
mvd[huffdec_packet_counter] = 0x100;
mvd[huffdec_cmdblock] = HUFFDEC_CMDBLOCK_MBA_ADDR;
}
/****************************************************************************
*
* Hufdec gateway fifo wait subroutines.
* Only works when the size of the two hufdec fifos are 16 dwords!
* Also it seems that we can't wait for more than 12!
*
*****************************************************************************/
#ifndef WAIT_HD_FIFO_USE_MACRO
void HUFF_wait_fifo_video(int number)
{
wait_huffdec_fifo(v, number);
}
void HUFF_wait_fifo_audio(int number)
{
wait_huffdec_fifo(a, number);
}
#endif
/****************************************************************************
*
* Various getbits subroutines.
*
*****************************************************************************/
int HUFF_autoeat(void) /* 8 or fewer bits */
{
do {} while ((mvd[huffdec_stat3] & 0xff) != 0xff);
return (((unsigned char *)mvd)[((huffdec_stat0)<<2)+3]);
}
int HUFF_getbits(int n) /* 8 or fewer bits */
{
assert(n <= 8);
mvd[huffdec_eatamount] = n - 1;
do {} while ((mvd[huffdec_stat3] & 0xff) != 0xff);
return (((unsigned char *)mvd)[((huffdec_stat0)<<2)+3]);
}
int HUFF_getbits_med(int n) /* up to 16 bits */
{
int answer;
assert(n <= 16);
mvd[huffdec_eatamount] = (n-1) & 7;
do {} while ((mvd[huffdec_stat3] & 0xff) != 0xff);
answer = ((unsigned char *)mvd)[((huffdec_stat0)<<2)+3];
if (n>8) {
mvd[huffdec_eatamount] = 7;
do {} while ((mvd[huffdec_stat3] & 0xff) != 0xff);
answer <<= 8;
answer |= ((unsigned char *)mvd)[((huffdec_stat0)<<2)+3];
}
return(answer);
}
int HUFF_getbits_big(int n) /* any number of bits */
{
int answer, status;
int n_bytes_left;
mvd[huffdec_eatamount] = (n-1) & 7;
do {} while ((mvd[huffdec_stat3] & 0xff) != 0xff);
answer = ((unsigned char *)mvd)[((huffdec_stat0)<<2)+3];
n_bytes_left = (n-1)>>3;
while (n_bytes_left-- > 0) {
mvd[huffdec_eatamount] = 7;
do {} while ((mvd[huffdec_stat3] & 0xff) != 0xff);
answer <<= 8;
answer |= ((unsigned char *)mvd)[((huffdec_stat0)<<2)+3];
}
return(answer);
}