Последовательный 4х проводный интерфейс.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Прошу подсказать по программной реализации.

Имеется микросхема - цифровой ресивер AK4118 с обменом последовательному интерфейсу. Хотелось бы прикрутить Ардуину для общения с этим чипом. Планируется реализовать переключение цифровых входов и вывод частоты на входе приёмника на дисплей.

Эпюры сигналов выглядят так

Насколько я понял:

1. вывод CSN в исходном состоянии имеет уровень лог. 1, а в моменты чтения-записи подтягивается к 0.

2. вывод CCLK - внешнее тактирование, должно выполняться от МК

3. выводы CDTI и CDTO - шины данных, при записи используется CDTI, а CDTО - отключена. При чтении используются обе - CDTI для задания адреса регистра, а CDTО для данных.

Высокоимпедансное (Hi-Z) состояние Атмега не умеет "выдавать", думается, придётся применить MOSFET  в цепи CDTО для реализации такой возможности, т.е потребуется 5 пинов МК (4 - под обмен, 1 - для управлением затвора полевика.)

Полный даташит в PDF на АК4118 можно скачать тут

Не затруднит ли кого пнуть меня в нужном направлении?

Datak
Offline
Зарегистрирован: 09.10.2014

OlegK пишет:

Высокоимпедансное (Hi-Z) состояние Атмега не умеет "выдавать"

Высоимпедансное состояние Атмега "выдаёт", если нога сконфигурирована как вход. Никто ведь не запрещает конфигурить её "на ходу", в процессе передачи/приёма данных.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

А, точно, про состояние "как вход" я и не подумал даже )) Спасибо!

ЗЫ. Если я правильно понял, то это SPI интерфейс?

Datak
Offline
Зарегистрирован: 09.10.2014

Кажется да, похож на него.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Почитал про протокол, в принципе уже что-то, более-менее, ясно. Но есть пара вопросов.

При записи, пакет состоит из двух байт (картинка в первом сообщении), а SPI.transfer() за раз шлёт только один. Значит нужно два раза подряд вызывать передачу - для старшего байта числа и для младшего? (Добавлено: Почитал - да, два раза передачу нужно делать. Ну или больше, если требуется)

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Что-то не выходит каменный цветок...

С чтением, вроде уже понятно, состояние регистров получаю.

По крайней мере оно соответствует дефолтным из ДШ.

А вот с записью не выходит, ничего не изменяется.

const byte WRITEINPUT = 0b00100011; //адрес регистра контроля входов
const byte TWOINPUT = 0b01001001; //то, что нужно записать. Текущее состояние - 0b01001000
void WriteRegister(byte address, byte data){
    digitalWrite(SS, LOW);
    SPI.transfer(address);
    SPI.transfer(data);
    digitalWrite(SS, HIGH);
}

Подсобит кто?

Datak
Offline
Зарегистрирован: 09.10.2014

Значение  address  в функцию правильно передаётся, бит R/W не забыли установить?

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Бит R/W первым делом проверил.

Как оказалось и с чтением не всё гладко тоже. Сейчас примерно объясню.

Чтение. Большинство регистров имеют дефолтные значения и указаны в ДШ. К примеру, что бы прочитать регистр контроля входов, я запрашиваю регистр 03H:

const byte READINPUT = 0b00000011; //адрес регистра + режим чтения

и передаю его сюда

byte ReadRegister(byte address){
    digitalWrite(SS, LOW);
    SPI.transfer(address);
    byte result = SPI.transfer(0x00);
    digitalWrite(SS, HIGH);
    return result;
}

В некоторых случаях (регистры 0H, 03H, 07H) получаю значение, соответствующее дефолтным. Для вышеуказанного 03H получается 01001000, где 3 последних бита IPS2, IPS1, IPS0 хранят состояние входа приёмника. А вот большинство регистров, при аналогичном чтении по соотв. адресам, почему-то возвращают 11111111. По идее, если бы не совпадали установки синхронизации, то для всех регистров получалась бы белиберда, но с каких то же читает правильно...

Настройки SPI такие

void SPI_Setup()
{
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  pinMode(MISO, INPUT);
  SPI.begin();
}

По записи. В предыдущем сообщении как раз попытка записать в регистр, что бы включить вход RX1 (последние три бита - 001), т.е. адрес, с включенным флагом записи будет выглядеть так -

const byte WRITEINPUT = 0b00100011; //адрес регистра + режим записи

а данные, которые будут записаны так -

const byte TWOINPUT = 0b01001001; //Текущее состояние - 0b01001000

т.е. изменён последний бит, относительно исходного. Ну и передаю в вышеуказанную процедуру записи, где передаю сперва адрес, а следом и данные. Бит разрешения записи включён. В теории должно записаться, но при последующем чтении получаю всё то же дефолтное значение, т.е. ничего не записывается.

Datak
Offline
Зарегистрирован: 09.10.2014

А разный SPI_MODE попробовали? Я их так, на память не помню, чтобы по картинке определить, но они гуглятся легко. По-моему, прямо в википедии всё было, даже в картинках.

-------

Upd: Посмотрел. Если верить их картинке, надо устанавливать SPI_MODE3. Хотя, ничего не обещаю конечно.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Пробовал, конечно, у нас же и смотрел тут.

 

С SPI_Mode0 как раз и выдаёт по некоторым регистрам то, что совпадает с начальными установками, с SPI_Mode1 тоже что-то пытается, но оно ни с чем не совпадает, а SPI_Mode2 и SPI_Mode3 - просто  единицы валит.

Вот в ДШ нашёл ещё такое -

The internal registers may be either written or read by the 4-wire μP interface pins: CSN, CCLK, CDTI & CDTO. The data on this interface consists of Chip address (1bit, C1 is fixed to “0”), Read/Write (1bit), Register address (MSB first, 5bits) and Control data (MSB first, 8bits).

Тут смущает, что биты расписаны - адрес, флаг R/W, адрес 5 бит и данные 8 бит. А в графике последовательность чуть другая - адрес, старший бит адреса, флаг записи-чтения, остальные биты адреса и байт данных. Хотя я и положение флага RW тоже менял - без толку.

Address and data is clocked in on the rising edge of CCLK and data is clocked out on the falling edge.

Тут также не очень понятно - адрес и данные по-разному синхронизируются, что ли?

For write operations, data is latched after the 16th rising edge of CCLK, after a high-to-low transition of CSN.

Т.е. запись осуществляется после 16 тактов и после смены уровня входа разрешения с высокого на низкий? Хм... А у меня, получается, не так. Или как правильно трактовать? Насколькоя понял - дёрнули CSN к 0, передали два байта (как раз 16 тактов) и отпустили к 1, ну и должно записаться...

For read operations, the CDTO output goes high impedance after a low-to-high transition of CSN.

И тут, непонятно - вроде, сперва нужно притянуть к 0 CSN, затем отправить адрес и следом, по другой ноге, считать "ответ", затем CSN "отпускаем" к 1. Ну, вышепоказанным эпюрам, вроде соответствует.

The maximum speed of CCLK is 5MHz.

Сейчас установлено 4МГц, т.е. нормально. Ставил совсем низкую частоту - тоже ерунда выходит.

Datak
Offline
Зарегистрирован: 09.10.2014

OlegK пишет:

С SPI_Mode0 как раз и выдаёт по некоторым регистрам то, что совпадает с начальными установками, с SPI_Mode1 тоже что-то пытается, но оно ни с чем не совпадает, а SPI_Mode2 и SPI_Mode3 - просто  единицы валит.

Верю конечно, но как это объяснить - не знаю. Вот их картинка:

А вот описание режимов.

режим 1 (CPOL = 0, CPHA = 0);
режим 2 (CPOL = 0, CPHA = 1);
режим 3 (CPOL = 1, CPHA = 0);
режим 4 (CPOL = 1, CPHA = 1).

Режимы тут, правда, с единицы нумеруются, но ведь наш режим, по-моему, последний - CPOL=1, CPHA=1.

Цитата:

The internal registers may be either written or read by the 4-wire μP interface pins: CSN, CCLK, CDTI & CDTO. The data on this interface consists of Chip address (1bit, C1 is fixed to “0”), Read/Write (1bit), Register address (MSB first, 5bits) and Control data (MSB first, 8bits). 

Да, похоже на ошибку. Только 7 бит описано, вместо восьми.

Цитата:

Address and data is clocked in on the rising edge of CCLK and data is clocked out on the falling edge.

Тут также не очень понятно - адрес и данные по-разному синхронизируются, что ли?

Это они, кажется, пишут что на линию данные выдаются (clocked out) по спаду тактовой, а читаются (clocked in) по фронту. Похоже на правду - картинке соответствует.

Цитата:

Или как правильно трактовать? Насколькоя понял - дёрнули CSN к 0, передали два байта (как раз 16 тактов) и отпустили к 1, ну и должно записаться...

Да, я понял так. То есть, выставили 0 на CSN - пошёл отсчёт тактов. На 16 такте данные записались в регистр. После этого CSN можно снимать, т.е. устанавливать в 1. 

Цитата:

 For read operations, the CDTO output goes high impedance after a low-to-high transition of CSN.

И тут, непонятно - вроде, сперва нужно притянуть к 0 CSN, затем отправить адрес и следом, по другой ноге, считать "ответ", затем CSN "отпускаем" к 1. Ну, вышепоказанным эпюрам, вроде соответствует.

По-моему, имеется в виду что последний прочитанный бит сохраняется на линии, пока не будет снят CSN. Возражений не имею, по-моему всё логично.

 

Даже не знаю, что посоветовать. Осциллографом бы ткнуть, конечно, и сравнить с картинкой.

Мне в таких случаях иногда проще написать то же самое программно, без использования контроллера. А уже потом, когда всё заработает, выяснять, чем сигналы контроллера отличаются от моих.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Фигня какая-то получается. Прогнал часть регистров, для которых в ДШ указано содержимое по-умолчанию,

Работало в режиме SPI_MODE0 - хоть что-то соответствует...

00H: 01000011 - соотв. дефолтному
01H: 01101010 - соотв. дефолтному
02H: 11111111 -> дефолтное 10001000
03H: 01001000 - соотв. дефолтному
04H: 11111111 -> дефолтное 11101110
05H: 11111111 -> дефолтное 10110101
06H: 11111111-> дефолтное 00000000
07H: 00010000 - соотв. дефолтному

20H: 11111111-> дефолтное 01110111
24H: 11111111-> дефолтное 00111111

SPI_MODE1

00H: 10000110
01H: 10000110
02H: 10000110
03H: 10000110
04H: 11010100
05H: 11010100
06H: 11010100
07H: 11010100
20H: 0
24H: 0
 

SPI_MODE2

00H: 10100001
01H: 10110101
02H: 11000100
03H: 10100100
04H: 11111111
05H: 11111111
06H: 10001000
07H: 10001000
20H: 11111111
24H: 11111111
 

SPI_MODE3

00H: 1000000
01H: 11111111
02H: 11111110
03H: 11111111
04H: 11111101
05H: 11111111
06H: 11111110
07H: 11111111
20H: 11101000
24H: 11111101
 

Вышеупомянутый ресивер работает в составе платы ЦАП и управляется контроллером от китайцев. Ну как управляется - показывает и позволяет выбрать один из 3х входов и индицирует входящую частоту. Но. Периодически подвисает и перстаёт реагировать на кнопки и менять показания, а так же не сохраняет выбранный вход. Ну и дополнить кое-чем хотелось бы. Китайский контроллер сделан на sm8951ac25pp - китайский клон неизвестно чего. SPI ноги ресивера подтянуты к + питания резисторами 10к.

Datak
Offline
Зарегистрирован: 09.10.2014

Серьёзно говорю, напишите тестовую программу, это не долго. :)
Хотя бы сможете выяснить, по какому фронту данные писать, и по какому читать.

Если нет осциллографа, прилепите на линии хотя бы светодиоды, и работайте на очень низкой частоте, чтобы мигания было видно.

Начните с чтения нулевого регистра. Для него ведь команда чтения состоит из одних нулей, если не ошибаюсь?

Вот и делайте по порядку, с интервалом, например, 1 секунда:
- переведите CDTI в 0
- переведите CSN в 0
- начините выдавать частоту на CCLK, тоже очень медленно
- если всё идёт как надо, где-то после 8-го такта должны пойти ответные данные по линии CDTO. Наша цель, для начала, просто выяснить, по какому фронту CCLK происходит изменение CDTO.

После этого можно переходить к следующему эксперименту - пробовать передавать на CDTI реальную команду. Биты на линии выставлять обязательно по тому же фронту, по которому изменялись входные данные на CDTO.

Потом, если нулевой регистр читается правильно, начинайте пробовать другие адреса.

Заработает оно, в конце концов, никуда не денется. :)

-------

Upd: Подумал, и решил что светодиоды - это не обязательно. Состояние ног, и входных и выходных, можно читать самой ардуиной, и выводить в сериал монитор.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Спасибо за посильную помощь, попробую, наверное, так, как вы советуете. Чудес не бывает, китайцы ж читают-пишут как-то. Что-бы очень медленно это реализовать, наверное, нужно софтовый SPI заюзать - в хардварном минимально можно f/128 получить (вроде как).

Пару дней перекурю ДШ с инетами, помыслю, может что ещё выяснить удастся...

Кстати, по другой железяке от этой же конторы (АК) вроде мелькнуло где-то про запись такое, мол есть пин PDN - это, типа, ресет, но

при записи его сперва посадить на 0, затем пишем в регистр, затем отпускаем к 1 этот пин. У 4118 тоже такая нога есть и она выведена на ШР, что идёт модуль управления. Но пока с чтением надо решить, запись потом...

VictorM
Offline
Зарегистрирован: 24.02.2015

Олег, за отправную точку вы можете взять проект из второго поста пользователя NinoSimona отсюда http://www.diyaudio.com/forums/digital-source/245905-ebay-weiliang-dual-x2-ak4399-dac-lcd-90.html. Уже все разработанно. Есть правда одна проблема, это все протестированно и работает на первой версии платы (с АК4113). Мне пока не удалось довести до работающего состояния на моей плате (с АК4118). Звука нет, хотя последовательности отдаются правильные. Может быть моя плата нерабочая, у меня и с оригинальным контроллером работает через одно место. Чтобы звук получить надо входы раз 20 переключать, а то и больше. Но буду дальше пробовать, со спеком сравнивать, ну и уже на всякий случай заказал на eBay первую версию на АК4113. Китайская продукция хороша лишь в том случае, если повезет.

Отпишитесь, если достигните успеха. Я уже прогу модернизировал, сделал возможность отключения подсветки дисплея, когда микроконтроллер уходит в спячку.

Ну, а оригинальный контроллер/программа полюбому кака.

PS:  Там надо регистрироваться, чтобы картинки и аттачмент видеть.

VictorM
Offline
Зарегистрирован: 24.02.2015

Пробежал сейчас по спекам 4118 и 4113. Особенных различий не нашел. Ну надо другой регистр читать после смены частоты или анлока, ну количество входов побольше, ну диэмфэсис пошире, а так практически одно и тоже. Странно на 4113 работает,а у меня частоту входную не захватывает.

А насчет SPI.transfer() все просто. Пин куда вы хотите писать ставится в Low, затем вызывается transfer нужное количество раз, затем пин ставится в High и данные передаются одновременно. Затем делается задержка минимум на 150ns.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

VictorM, большое спасибо за ссылку, гляну (я там, оказывается, зарегистрирован) сразу, как только получится - переключился на "доделать" сверлилку для плат.

А вообще, там нужно (всмысле на моей плате) уточнить с уровнями, ибо микросхема ресивера питается от 3.3V, её управляющие ноги подтянуты к +5V, а на стороне МК ещё раз подтянуты к той же самой 5 вольтовой шине. Я вот думаю, отрезать подтяжку к 5V, пересадить на 3.3, а сигналы от МК к ресиверу подать через резисторы.

КМК, так будет правильнее...

VictorM
Offline
Зарегистрирован: 24.02.2015

Насколько я понял, нужно только ногу TVDD на 5V подтянуть, она на 3.3V сидит. Одно значимое отличие 4113 от 4118 в том, что у 4113 на этой ноге Max 6V, а у 4118 только 5.5V. Я пока не сделал, может поэтому не работает.

Мне очень интересно заработает ли у вас. Там переделки очень небольшие - соединить пару ног обоих коннекторов, и припаять проводок на ногу INT0(для начала можно времянку кинуть).

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

VictorM пишет:
ногу TVDD на 5V подтянуть, она на 3.3V сидит.
На плате, относительно проблематично это выполнить, а вот конвертер уровней на резисторах добавить проще, думаю. Лишь бы величина лог 1 не превышала нормальную величину. С другой стороны, китайский контроллер работает же как-то и ничего не дохнет...

Цитата:
Мне очень интересно заработает ли у вас.
Мне тоже ))) Правда, пока планируется сделать управление ресивером, а вот для ЦАПа время позже придёт, когда приедет плата на 4490 (сейчас у меня на 4495-м ЦАпе) - там поле для деятельности гораздо шире и проект по вашей ссылке очень будет кстати.

Цитата:
Там переделки очень небольшие - соединить пару ног обоих коннекторов, и припаять проводок на ногу INT0(для начала можно времянку кинуть).
Не понял, каких коннекторов?

 

VictorM
Offline
Зарегистрирован: 24.02.2015

Там по ссылка речь о плате на 4118 и 4399, на ней два коннектора для МК 4х штырьковый и 10ти штырьковый.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

А, понятно. У меня плата на 4495+4118, там задействован только один 10-пиновый коннектор (хотя на плате МК их пара). Управление, соответственно, реализовано только ресивером (переключение входов и  индикация частоты), а ЦАП включён в режим параллельного управления - доступен только выбор хар-ки ЦФ джамперами.

VictorM
Offline
Зарегистрирован: 24.02.2015

Олег, у меня к вам один вопрос. Вы эту плату как кит покупали и сами паяли или купили уже готовую?

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Китов, на тот момент, у китайцев, предлагался только один, по стоимости чуть меньшей, чем собранная плата, поэтому, пришлось брать собранную. СОбрано, кстати, хорошо и аккуратно, комплектуха неплохая. Хотя, чуть бы кто пораньше подсказал, я взял бы другую, на АК4490 - чисто ЦАП, без ресивера, питания и выхлопа, просто с входом I2C, под USB транспорт, ибо мне, в принципе, только ЮСБ вход и нужен. Возможно, так и сделаю, а эту, на АК4495 - на продажу. Звук, кстати, у этих АК очень неплохой, НЧ очень "вкусные", особенно, после замены стокового ОУ на AD823. У меня был ЦАП на 4х PCM1704, тот звучал, таки, более плоско и менее прозрачно, вкупе с со смягчённым низом.

VictorM
Offline
Зарегистрирован: 24.02.2015

Выхлоп там надо полюбому переделывать, и не на одном ОР, со своим источником питания прямо на платке выхлопа. А питание Цапа, я все равно буду переделывать, буду ставить маленькие платки ультралоунойс стабов вместо конденсаторов, минимум по два на канал ЦАПа.

Я бы взял кит, да боюсь, что лабуду подсунут, спаяешь, а он не работает. Наверное возьму готовую, выберу потом из всего то, что лучше звучит. У меня еще и ЦАП на 8ми PCM1702 не до конца доделан, но у него плата уж больно здоровая. Посмотрим, что старый честный мультибит по сравнению с современным дельта сигма покажет.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

VictorM пишет:
А питание Цапа, я все равно буду переделывать, буду ставить маленькие платки ультралоунойс стабов вместо конденсаторов, минимум по два на канал ЦАПа.

Как варианты -

1. Стоковый стаб + стабы на ADM7159/7151 для раздельных цепей

2. Стоковый стаб + параллельные стабы, аналогично.

Цитата:
Я бы взял кит, да боюсь, что лабуду подсунут, спаяешь, а он не работает.

Или комплектуху не полностью положат (сталкивался уже). Наверное, лучше спаянный и проверенный (заострить на этом внимание продавана).

Цитата:
Посмотрим, что старый честный мультибит по сравнения с современным дельта сигма покажет.

Интересно было бы узнать ))

mkvmaks
Offline
Зарегистрирован: 07.07.2013

Нубский вопрос: где прочитать про то, как парвильно такие каринки как у топикстартера  преобразовать в код??? Как работать с битами данных? 

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

mkvmaks, вам конкретный протокол (к примеру, SPI, I2C, 1Wire) нужен? Ну, почитайте про библиотеки SPI и Wire, поищите примеры использования с конкретными устройствами (датчики, микросхемы), сравните с даташитом, где подобные эпюры расписаны, потом пробуйте применить для того, для чего планируете. Возможно, уже есть что-то именно нужное вам - можете разобрать код и прикинуть, что к чему. Ну а там по текущим успехам...