Hello,
I need some help with my I2C Menu app... I created a new Codec board out of a TLV320AIC3105 chip. It's powered on, and I'm communicating with it via I2C (yay!). I've done this before with a few other chips, and I created an "I2C_menu" app so that I can just send a few I2C commands to the chip. This allows me to confirm that the hardware is working, and confirm the steps involved for initialization of the new chip, so that I can begin to write a driver for it.
The code is as follows.
When I use case 3, I get a dump of all the registry values. Then at the end, it concludes, and returns to printMenu() and then wait for another serial.read input.
But case 5 (Dump specific register) causes the Teensy 4.0 to crash and then restart (showing "setup" in the serial monitor). It crashes right after the readValue() function. I suspect it has something to do with Serial.readStringUntil() not releasing or something? I can not figure out why the teensy crashes here (see the "Setup" in the text below). Any idea?
PS - Arduino has a known bug not allowing select all and copy of the entire serial monitor so my examples are truncated.
If anyone has any clue why the Teensy is crashing and resetting on "case 5", please help. Thank you!
Jay
I need some help with my I2C Menu app... I created a new Codec board out of a TLV320AIC3105 chip. It's powered on, and I'm communicating with it via I2C (yay!). I've done this before with a few other chips, and I created an "I2C_menu" app so that I can just send a few I2C commands to the chip. This allows me to confirm that the hardware is working, and confirm the steps involved for initialization of the new chip, so that I can begin to write a driver for it.
The code is as follows.
Code:
/*
I2C Menu + Audio
Run this with Serial - Midi - Audio board type.
(build_flags = -D USB_MIDI_AUDIO_SERIAL)
License: MIT License. Use at your own risk.
*/
#include <Wire.h>
#include <Audio.h>
#include <SPI.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioInputI2S i2s3; //xy=190.33333587646484,431.3333930969238
AudioInputUSB usb1; //xy=208.3333282470703,498.3333435058594
AudioMixer4 mixer1; //xy=394.3333549499512,471.3333559036255
AudioOutputI2S i2s1; //xy=540.3333015441895,503.33335876464844
AudioConnection patchCord1(i2s3, 0, mixer1, 2);
AudioConnection patchCord2(i2s3, 1, mixer1, 3);
AudioConnection patchCord3(usb1, 0, mixer1, 0);
AudioConnection patchCord4(usb1, 1, mixer1, 1);
AudioConnection patchCord5(mixer1, 0, i2s1, 0);
AudioConnection patchCord6(mixer1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=310.3333282470703,613.3333435058594
// GUItool: end automatically generated code
uint8_t currentI2C_addr = 0x18;
int currentPage = 0;
void setup() {
Serial.println("Setup");
Serial.println("");
Serial.println("");
Serial.println("");
Serial.println("");
AudioMemory(100);
Wire.begin();
delay(5); // wait for steady I2C line
Serial.begin(9600);
Serial.setTimeout(999999);
delay(1000);
}
void loop() {
Serial.println("Loop");
menu();
}
void scanI2C()
{
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for (address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
delay(5);
error = Wire.endTransmission();
if (error == 0)
{
Serial.println("\nI2C device found at address 0x");
if (address < 16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println("!");
nDevices++;
}
else if (error == 4)
{
Serial.print("\nUnknown error at address 0x");
if (address < 16)
Serial.print("0");
Serial.println(address, HEX);
}
else {
if (address == 32 || address == 64 || address == 96) {
Serial.print(".\n");
} else {
Serial.print(".");
}
}
}
if (nDevices == 0)
Serial.println("\nNo I2C devices found\n");
else
Serial.println("done\n");
}
void moveI2C_addr() {
byte error = 1;
uint8_t xx;
xx = inputHexValue(1);
Serial.print("\nAttempting to switch current I2C address to ");
PrintHex8(&xx, 1);
Serial.println();
Wire.beginTransmission(xx);
delay(5);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address ");
PrintHex8(&xx, 1);
currentI2C_addr = xx;
Serial.println("!");
} else {
Serial.print("Unable to connect to I2C device at address ");
PrintHex8(&xx, 1);
Serial.println("!");
Serial.print("Current I2C address not changed!\n\n\n");
}
}
uint8_t inputHexValue(int n) {
//Take the input
Serial.println("\n\nInput one hex value,");
Serial.println("i.e. 0x4C");
Serial.print("Input: ");
Serial.readStringUntil('\n');
// Serial.setTimeout(999999);
String param = Serial.readStringUntil('\n');
Serial.print(param);
//Process the results into xx
char buf[5];
param.toCharArray(buf, 5);
uint8_t xx;
sscanf(buf, " %x", &xx);
// Print the results
Serial.println();
Serial.print("Decimal: "); Serial.print(xx);
Serial.println();
Serial.print("Hex: "); PrintHex8(&xx, 1);
Serial.println();
return xx;
}
void printResults(uint8_t val) {
Serial.print(" "); Serial.print(val);
Serial.println();
Serial.print(" Hex: "); PrintHex8(&val, 1);
Serial.println();
Serial.print(" Bin: "); Serial.println(val,BIN);
}
void readI2C_command() {
String param;
uint8_t xx = 0;
uint8_t yy = 0;
//accept input
Serial.println("\nInput the page and register (in hex) you wish to read,");
Serial.println("i.e. 0x01 0x03");
Serial.print("\nInput: ");
if (Serial.available()) {
Serial.read();
param = Serial.readStringUntil('\n');
Serial.println(param);
}
//process values
Serial.println("Process Values");
char buf[20];
param.toCharArray(buf, 20);
sscanf(buf, "%x %x", &xx, &yy);
//display the results
Serial.print("Page: "); printResults(xx);
Serial.print("Reg: "); printResults(yy);
//Read the value
readValue(xx, yy);
}
void writeI2C_command() {
Serial.println("\nInput the page, register, and value (in hex) you wish to write,");
Serial.println("i.e. 0x01 0x3F 0x00");
Serial.readStringUntil('\n');
// Serial.setTimeout(999999);
Serial.print("\nInput: ");
String param = Serial.readStringUntil('\n');
Serial.println(param);
//process values
char buf[25];
param.toCharArray(buf, 25);
uint8_t xx;
uint8_t yy;
uint8_t zz;
sscanf(buf, "%x %x %x", &xx, &yy, &zz);
//Print Results
Serial.print("Page: "); printResults(xx);
Serial.print("Reg: "); printResults(yy);
Serial.print("Value: "); printResults(zz);
// Write Page
writePage(xx, yy, zz);
}
void dumpAllRegisters() {
Serial.println("\nDumping all registers...");
currentPage = 0;
for (int reg = 1; reg <= 121; reg++) {
readValue(currentPage, reg);
delay(2);
}
currentPage = 1;
for (int reg = 1; reg <= 9; reg++) {
readValue(currentPage, reg);
delay(2);
}
}
void readValue(uint8_t page, uint8_t reg) {
Serial.println("");
Serial.println("Read Value");
uint8_t val;
if (goToPage(page)) {
Wire.beginTransmission(currentI2C_addr);
Wire.write(reg);
uint8_t result = Wire.endTransmission();
if (result != 0) {
Serial.print("readValue: ERROR: Read Page.");
Serial.print(" Page: "); printResults(page);
Serial.print(" Reg: "); printResults(reg);
Serial.println(". Received Error During Read Page: ");
//val = 300 + result;
return;
}
if (Wire.requestFrom(currentI2C_addr, 1) < 1) {
Serial.print("readValue: ERROR: Read Page.");
Serial.print(" Page: "); printResults(page);
Serial.print(" Reg: "); printResults(reg);
Serial.println(". Nothing to return");
return;
}
if (Wire.available() >= 1) {
Wire.beginTransmission(currentI2C_addr);
Serial.println("readValue: Read Value.");
Serial.print(" Page: "); printResults(page);
Serial.print(" Reg: "); printResults(reg);
uint8_t val = Wire.read(); delay(10);
Serial.print("Received: "); printResults(val);
Wire.endTransmission(); delay(10);
return;
}
return;
}
else {
Serial.print("control: INFO: Read Page. Page: "); Serial.print(page);
Serial.print(" Reg: "); Serial.print(reg); Serial.print(" ");
Serial.println(". Failed to go to read page. Could not go there.");
//val = 500;
return;
}
//val = 600;
Serial.print(val);
//return val;
}
bool goToPage(byte page) {
Wire.beginTransmission(currentI2C_addr);
Wire.write(0x00); delay(10);// page register //was delay(10) from BPF
Wire.write(page); delay(10);// go to page //was delay(10) from BPF
byte result = Wire.endTransmission();
if (result != 0) {
Serial.print("control: Received Error During goToPage(): Error = ");
Serial.println(result);
if (result == 2) {
// failed to transmit address
//return goToPage(page);
} else if (result == 3) {
// failed to transmit data
//return goToPage(page);
}
return false;
}
return true;
}
/*
void transmit_exported_registers(cfg_reg *r, int n) {
Serial.println("Beginning to transmit exported registers...");
int i = 0;
while (i < n) {
Wire.beginTransmission(currentI2C_addr);
Serial.print("r[");
Serial.print(i);
Serial.print("].command: ");
// PrintHex8(r[i].command, 1);
Wire.write(r[i].command); delay(10);
Serial.print("r[");
Serial.print(i);
Serial.print("].param: ");
Serial.println(r[i].param, HEX);
Wire.write(r[i].param); delay(10);
Wire.endTransmission();
i++;
}
Serial.println("Finished transmitting all dumped register values");
}
*/
boolean writePage(uint8_t page, uint8_t reg, uint8_t val) {
Serial.println("control: Write Page.");
Serial.print("Page: "); printResults(page);
Serial.print("Reg: "); printResults(reg);
Serial.print("Value: "); printResults(val);
if (goToPage(page)) {
Wire.beginTransmission(currentI2C_addr);
Wire.write(reg); delay(10);
Wire.write(val); delay(10);
uint8_t result = Wire.endTransmission();
if (result == 0) return true;
else {
Serial.print("control: Received Error During writePage(): Error = ");
Serial.println(result);
}
}
readValue(page, reg);
return false;
}
void printMenu() {
Serial.flush();
Serial.println();
Serial.println();
Serial.println();
Serial.println();
Serial.println();
Serial.println("Test menu:");
Serial.println("---------------------------------------");
Serial.print("Current I2C Address: ");
PrintHex8(¤tI2C_addr, 1);
Serial.println("(" + String(currentI2C_addr) + ")");
Serial.println("Available options: ");
Serial.println("1: Move to different I2C address");
Serial.println("2: Scan I2C address space");
Serial.println("3: Dump all registers");
Serial.println("4: Write all preprogrammed registers");
Serial.println("5: Dump specific register");
Serial.println("6: Write specific register");
Serial.println("---------------------------------------");
Serial.print("Input: ");
}
void menu() {
printMenu();
for (;;) {
switch (Serial.read()) {
case '1': {
Serial.print("1");
moveI2C_addr();
printMenu();
break;
}
case '2': {
Serial.print("2");
scanI2C();
printMenu();
break;
}
case '3': {
Serial.print("3");
dumpAllRegisters();
printMenu();
break;
}
case '4': {
Serial.print("4");
/*
transmit_exported_registers(registers, sizeof(registers) / sizeof(registers[0]));
printMenu();
break;
*/
}
case '5': {
Serial.print("5");
readI2C_command();
printMenu();
break;
}
case '6': {
Serial.print("6");
writeI2C_command();
printMenu();
break;
}
default:
continue; // includes the case 'no input'
}
}
}
void PrintHex8(uint8_t *data, uint8_t length) // prints 8-bit data in hex with leading zeroes
{
char tmp[16];
for (int i = 0; i < length; i++) {
sprintf(tmp, "0x%.2X", data[i]);
Serial.print(tmp); Serial.print(" ");
}
}
When I use case 3, I get a dump of all the registry values. Then at the end, it concludes, and returns to printMenu() and then wait for another serial.read input.
Code:
3
Dumping all registers...
Read Value
readValue: Read Value.
Page: 0
Hex: 0x00
Bin: 0
Reg: 1
Hex: 0x01
Bin: 1
Received: 0
Hex: 0x00
Bin: 0
Read Value
readValue: Read Value.
Page: 0
Hex: 0x00
Bin: 0
Reg: 2
Hex: 0x02
Bin: 10
Received: 16
Hex: 0x10
Bin: 10000
...
But case 5 (Dump specific register) causes the Teensy 4.0 to crash and then restart (showing "setup" in the serial monitor). It crashes right after the readValue() function. I suspect it has something to do with Serial.readStringUntil() not releasing or something? I can not figure out why the teensy crashes here (see the "Setup" in the text below). Any idea?
Code:
5
Input the page and register (in hex) you wish to read,
i.e. 0x01 0x03
Input: 0x01 0x09
Process Values
Page: 1
Hex: 0x01
Bin: 1
Reg: 9
Hex: 0x09
Bin: 1001
Read Value
readValue: Read Value.
Page: 1
Hex: 0x01
Bin: 1
Reg: 9
Hex: 0x09
Bin: 1001
Received: 102
Hex: 0x66
Bin: 1100110
Setup...
PS - Arduino has a known bug not allowing select all and copy of the entire serial monitor so my examples are truncated.
If anyone has any clue why the Teensy is crashing and resetting on "case 5", please help. Thank you!
Jay