/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Created on 01.09.2005
*
*/
package dsp;
import joprt.RtThread;
import com.jopdesign.sys.*;
/**
* @author Martin Schoeberl (martin@jopdesign.com)
*
*/
public class AC97 {
public static final int CSR = 0x0/4; // Main Configuration/Status Register
public static final int OCC0 = 0x4/4; // RO Output Channel Configuration Register 0
public static final int OCC1 = 0x8/4; // Output Channel Configuration Register 1
public static final int ICC = 0xc/4; // Input Channel Configuration Register
public static final int CRAC = 0x10/4; // Codec Register Access Command
public static final int INTM = 0x14/4; // Interrupt Mask
public static final int INTS = 0x18/4; // Interrupt Status Register
public static final int RES = 0x1c;
public static final int OCH0 = 0x20/4; // Output Channel 0
public static final int OCH1 = 0x24/4; // Output Channel 1
public static final int OCH2 = 0x28/4; // Output Channel 2
public static final int OCH3 = 0x2c/4; // Output Channel 3
public static final int OCH4 = 0x30/4; // Output Channel 4
public static final int OCH5 = 0x34/4; // Output Channel 5
public static final int ICH0 = 0x38/4; // Input Channel 0
public static final int ICH1 = 0x3c/4; // Input Channel 1
public static final int ICH2 = 0x40/4; // Input Channel 2
public static final int MSK_RD_DONE = 0x01;
public static final int MSK_WR_DONE = 0x02;
public static int rd(int wb_reg) {
return Native.rdMem(Const.WB_AC97+wb_reg);
}
public static void wr(int wb_reg, int val) {
Native.wrMem(val, Const.WB_AC97+wb_reg);
}
/**
* Codec register read
* @param reg
* @return
*/
public static int codecRd(int reg) {
wr(CRAC, 0x80000000+(reg<<16));
while((rd(INTS) & MSK_RD_DONE)==0) {
; // busy wait till value read
}
return rd(CRAC)&0xffff;
}
/**
* Codec register read
* @param reg
* @param val
*/
public static void codecWr(int reg, int val) {
wr(CRAC, (reg<<16)+val);
while((rd(INTS) & MSK_WR_DONE)==0) {
; // busy wait till write done
}
}
public static void init() {
//
// check status register and force a reset
//
System.out.println("CSR="+rd(CSR));
wr(CSR, 1); // cold reset the AC97
System.out.println("CSR="+rd(CSR));
RtThread.sleepMs(10);
System.out.println("CSR="+rd(CSR));
wr(CSR, 2); // resume the AC97
RtThread.sleepMs(10);
System.out.println("CSR="+rd(CSR));
//
// enable stereo in and out in the AC97 interface
//
System.out.println("OCC0="+rd(OCC0));
wr(OCC0, 0x0101); // enable front left and right output
// wr(OCC0, 0x0909); // enable front left and right output
System.out.println("OCC0="+rd(OCC0));
wr(ICC, 0x2121); // enable left and right input
// wr(ICC, 0x0909); // enable left and right input
System.out.println("ICC="+rd(ICC));
//
// read some vendor information
//
System.out.println("VENDOR ID="+codecRd(0x7c));
System.out.println("VENDOR version="+codecRd(0x7e));
//
// do the initilization
//
System.out.println("MASTER VOLUME="+codecRd(0x02));
codecWr(0x02, 0x0000); // unmute master volume
System.out.println("MASTER VOLUME="+codecRd(0x02));
// codecWr(0x10, 0x0808); // enable line input
codecWr(0x18, 0x0808); // PCM-out volume
codecWr(0x1a, 0x0404); // select line record
codecWr(0x1c, 0x0000); // record gain
// codecWr(0x20, 0x0000); // local loopback
// codecWr(0x64, 0x0000); // mixer adc, input gain
}
public static void run() {
int left, right, i, j, v1, v2;
for (i=0; i<10; ++i) {
// flush input FIFOs
rd(ICH0);
rd(ICH1);
rd(INTS);
}
i = 0;
for (;;) {
// busy wait for input samples
for (;;) {
int status =Native.rdMem(Const.WB_AC97+INTS);
if ((status&0x2d00000)!=0) break;
}
left = Native.rdMem(Const.WB_AC97+ICH0);
right = Native.rdMem(Const.WB_AC97+ICH1);
// if ((Native.rdMem(Const.WB_AC97+INTS)&0x1200000)!=0) {
// continue;
// }
Native.wrMem(left, Const.WB_AC97+OCH0);
Native.wrMem(right, Const.WB_AC97+OCH1);
}
}
public static void main(String[] args) {
init();
run();
}
}