streaming server for AM/FM radio via UDP connection.
Dependencies: mbed EthernetNetIf
ns9542.c
- Committer:
- soramimi
- Date:
- 2011-03-25
- Revision:
- 1:3357273c97f8
- Parent:
- 0:bd865e5a3df3
File content as of revision 1:3357273c97f8:
#include "mbed.h" //I2C i2c(p9, p10); // sda, scl DigitalInOut i2c_sda(p9); DigitalInOut i2c_scl(p10); void wait10us() { wait(0.000001); } void wait10ms() { wait(0.001); } void wait100ms() { wait(0.01); } #if 1 // i2c void i2c_cl_0() { i2c_scl.output(); } void i2c_cl_1() { i2c_scl.input(); } void i2c_da_0() { i2c_sda.output(); } void i2c_da_1() { i2c_sda.input(); } int i2c_get_da() { return i2c_sda.read(); } void i2c_start() { i2c_da_0(); wait10us(); i2c_cl_0(); wait10us(); } void i2c_stop() { i2c_cl_1(); wait10us(); i2c_da_1(); wait10us(); } void i2c_repeat() { i2c_cl_1(); wait10us(); i2c_da_0(); wait10us(); i2c_cl_0(); wait10us(); } bool i2c_write(int c) { int i; bool nack; wait10us(); for (i = 0; i < 8; i++) { if (c & 0x80) { i2c_da_1(); } else { i2c_da_0(); } c <<= 1; wait10us(); i2c_cl_1(); wait10us(); i2c_cl_0(); wait10us(); } i2c_da_1(); wait10us(); i2c_cl_1(); wait10us(); nack = i2c_get_da(); i2c_cl_0(); return nack; } int i2c_read(bool nack) { int i, c; i2c_da_1(); wait10us(); c = 0; for (i = 0; i < 8; i++) { i2c_cl_1(); wait10us(); c <<= 1; if (i2c_get_da()) { c |= 1; } i2c_cl_0(); wait10us(); } if (nack) { i2c_da_1(); } else { i2c_da_0(); } wait10us(); i2c_cl_1(); wait10us(); i2c_cl_0(); wait10us(); return c; } #endif // ns9542 void ns9542_write(int a, int c) { #if 01 i2c_start(); i2c_write(0xc8); i2c_write(a); i2c_write(c); i2c_stop(); #else char tmp[2]; i2c.start(); tmp[0] = a; tmp[1] = c; i2c.write(0xc8, tmp, 2); i2c.stop(); #endif } int ns9542_read(int a) { #if 01 int c; i2c_start(); i2c_write(0xc8); i2c_write(a); i2c_repeat(); i2c_write(0xc9); c = i2c_read(true); i2c_stop(); return c; #else char tmp[2]; i2c.start(); tmp[0] = a; tmp[1] = 0xc9; i2c.write(0xc8, tmp, 1); i2c.write(0xc8, tmp + 1, 1, true); unsigned char c = i2c.read(1); i2c.stop(); return c; #endif } void ns9542_imf_adjust() { int bF, imf, fhm, g_fhm; bF = 0; g_fhm = 0xf0; ns9542_write(0x15, 0x0e); ns9542_write(0x3d, 0x27); for (fhm = 0; fhm < 4; fhm++) { bF = 0; for (imf = 0; imf < 3; imf++) { ns9542_write(0x37, fhm); ns9542_write(0x16, 22 + imf); wait10ms(); if ((ns9542_read(0x70) & 0x0c) == 0x0c) { bF++; if (imf == 1 && g_fhm == 0xf0) { g_fhm = fhm; } } } if (bF == 3) { g_fhm = fhm; break; } } ns9542_write(0x37, 0x80 | g_fhm); ns9542_write(0x16, 23); ns9542_write(0x3d, 0x37); wait100ms(); } void ns9542_best_iml(int iml) { ns9542_write(0x32, 0x00); while (iml < 16) { ns9542_write(0x17, 0xc0 | iml); wait10ms(); if (!(ns9542_read(0x70) & 0x08)) { break; } iml++; } iml--; ns9542_write(0x17, 0xc0 | iml); ns9542_write(0x32, 0x80); wait10ms(); ns9542_write(0xfe, 0x0a); wait10ms(); wait10ms(); } void ns9542_find_pg(int ialgn, int *fine_phase, int *fine_gain, int *result_pg) { int i, j; for (i = 0; i < 16; i++) { ns9542_write(0x15, 0x0a | (ialgn << 4)); ns9542_write(0x15, 0x0b | (ialgn << 4)); if (ns9542_read(0x05) & 0x08) { for (j = 0; j < 20; j++) { if (!(ns9542_read(0x05) & 0x08)) { int g = ns9542_read(0x65); int p = ns9542_read(0x66); if (g >= 103 && g <= 138 && 2 >= p && p <= 14) { *fine_gain = g; *fine_phase = p; *result_pg = 1; return; } } wait10ms(); } } } *result_pg = 0; } void ns9542_table_write(int *fine_p, int *fine_g) { int i, j, k, result; result = 0; for (i = 0; i < 4; i++) { ns9542_write(0x38, fine_g[i]); ns9542_write(0x39, fine_p[i] << 4); for (j = 0; j < 10; j++) { ns9542_write(0x15, 0x0e | (i << 4)); ns9542_write(0x15, 0x03 | (i << 4)); if (ns9542_read(0x05) & 0x08) { wait100ms(); for (k = 0; k < 10; k++) { if (!(ns9542_read(0x05) & 0x08)) { result++; goto L1; } wait10ms(); } break; } } L1:; if (result != i + 1) { break; } } } void ns9542_dsp_align_body() { int iml, imf, ialgn, cnt, fp, fg; int fine_p[5] = { 0, 0, 0, 0, 0 }; int fine_g[5] = { 0, 0, 0, 0, 0 }; iml = 5; for (ialgn = 0; ialgn < 4; ialgn++) { ns9542_write(0x15, 0x0a | (ialgn << 4)); wait100ms(); wait100ms(); ns9542_best_iml(iml); imf = 0; cnt = 0; fp = 0; fg = 0; for (cnt = 0; cnt < 5; cnt++) { int fine_phase, fine_gain, result_pg; ns9542_find_pg(ialgn, &fine_phase, &fine_gain, &result_pg); if (result_pg == 0) { return; } fp = fp + fine_phase; fg = fg + fine_gain; if (cnt == 2 && ialgn < 2) { cnt++; break; } } fine_p[ialgn] = fp / cnt; fine_g[ialgn] = fg / cnt; } ns9542_table_write(fine_p, fine_g); } void ns9542_mute(bool mute) { if (mute) { ns9542_write(0x00, ns9542_read(0x00) | 0x02); } else { ns9542_write(0x00, ns9542_read(0x00) & ~0x02); } } void ns9542_tune_am9(int freq) // freq = kHz { unsigned short psy; psy = freq; ns9542_write(0x00, 0x23); wait10ms(); wait10ms(); ns9542_write(0x04, 0x80); ns9542_write(0x0c, 0xf0); ns9542_write(0x10, 0x10); ns9542_write(0x02, psy & 0xff); ns9542_write(0x03, psy >> 8); ns9542_write(0x00, 0x21); } void ns9542_tune_fm(int freq) // freq = MHz * 100 { unsigned short psy; psy = freq / 5; ns9542_write(0x00, 0x03); ns9542_write(0x10, 0x10); ns9542_write(0x02, psy & 0xff); ns9542_write(0x03, psy >> 8); ns9542_write(0x00, 0x01); } void ns9542_reset() { ns9542_write(0xfe, 0xaa); } void ns9542_power_on() { static unsigned char power_on[] = { 0x01, 0x30, 0x0c, 0x80, 0x0e, 0x34, 0x15, 0xc4, 0x20, 0x3c, 0x21, 0x03, 0x22, 0x0a, 0x23, 0x0a, 0x30, 0xff, 0x3d, 0x07, 0x40, 0x1a, 0x41, 0x9a, 0x50, 0xe1, 0x54, 0xb0, 0x55, 0x36, 0x5c, 0xc8, 0x5d, 0x61, 0x5e, 0x88, 0x5f, 0xa5, 0x71, 0x2c, 0x72, 0x06, }; int i; for (i = 0; i < sizeof(power_on); i += 2) { ns9542_write(power_on[i], power_on[i + 1]); } ns9542_write(0x00, ns9542_read(0x00) | 0x03); } void ns9542_dsp_alignment() { ns9542_write(0x0e, ns9542_read(0x0e) & ~0x60 | 0x40); ns9542_write(0x01, 0x08); ns9542_write(0x15, 0x0c); ns9542_write(0x16, 0x17); ns9542_write(0x37, 0x82); ns9542_write(0x3d, 0x37); wait100ms(); ns9542_imf_adjust(); ns9542_dsp_align_body(); ns9542_write(0x01, 0x38); ns9542_write(0x0e, ns9542_read(0x0e) & ~0x60 | 0x20); ns9542_write(0x15, 0xc0); ns9542_write(0x17, 0x20); ns9542_write(0x32, 0x00); ns9542_write(0x37, 0x01); } void ns9542_init() { i2c_sda.mode(PullUp); i2c_scl.mode(PullUp); i2c_sda.input(); i2c_scl.input(); i2c_sda.write(0); i2c_scl.write(0); ns9542_reset(); ns9542_power_on(); ns9542_dsp_alignment(); }