Vou falar um pouco sobre o clock Bluetooth, e sobre o protocolo MCAP CSP.
Cada dispositivo Bluetooth tem um relógio interno, nunca reajustado, que pulsa 3200 vezes por segundo. Esse relógio incrementa um contador de 28 bits, que "faz a volta" em pouco menos de um dia. O relógio BT pode ser lido por qualquer aplicativo via um soquete HCI.
Desse relógio depende muita coisa do BT, como por exemplo os "saltos" pelos canais de rádio, que acontecem na metade da velocidade do relógio (1600 saltos por segundo).
Numa piconet há um mestre e diversos escravos. Todos precisam saltar os canais de rádio no mesmo ritmo para que possam comunicar-se, o que implica que o clock dos participantes esteja sincronizado. O clock dos escravos é mantido sincronizado pela adição de um valor (offset) de modo que
clock local + offset = clock do mestre
No mestre, o offset é zero. Como a precisão do clock BT não é nenhuma Brastemp (e diminui muito quando o dispositivo BT não está ativo), os escravos devem reajustar periodicamente o offset.
Um dispositivo BT pode participar (como escravo) de mais de uma piconet. Se houver duas piconets, temos três clocks possíveis: o local, o do mestre 1, e o do mestre 2 (obtidos pela adição do offset da piconet 1 ou 2, respectivamente).
Assim, quando lermos o clock da piconet usando o soquete HCI, temos de especificar uma conexão ACL (o canal assíncrono entre um par de dispositivos), o que indiretamente especifica a piconet. Naturalmente, não precisamos especificar nada para ler o clock local.
Podemos imaginar uma situação em que diversos dispositivos Bluetooth estejam mandando informações, e gostaríamos de saber o momento exato, ou timestamp, relativo a cada informação.
O exemplo canônico é uma esteira rolante com diversos sensores óticos. Quando um objeto passar pela esteira, vai disparando os sensores, que informam os eventos a um concentrador.
Se o concentrador quiser determinar a velocidade do objeto, não pode confiar na ordem ou no instante de recebimento do evento, pois pode haver todo tipo de atraso na transmissão. É o sensor que tem de "carimbar" o timestamp no evento, para então enviá-lo.
Aí vem o problema seguinte: para que os timestamps de diversos sensores sejam comparáveis, é preciso que estejam sincronizados. De alguma forma, o concentrador tem de resetar todos os sensores num mesmo instante, o que não é trivial. Mesmo com broadcast, sempre haverá um atraso na entrega ou no processamento, e os relógios dos diversos sensores ficariam diferentes.
No caso do Bluetooth, temos um clock comum sincronizado, que é o clock da piconet, porém sua precisão e resolução deixam a desejar.
Por outro lado, a precisão e a resolução do relógio do sistema operacional — vamos chamá-lo de "hora civil", pois costuma corresponder à data/hora — costumam ser muito boas, mas não é um clock facilmente sincronizável. É certo que a data/hora de cada sensor será um pouco diferente.
Mesmo que o concentrador tivesse como zerar instantaneamente a hora civil de todos os sensores, eles apresentarão um desvio (drift) variado, e depois de certo tempo os relógios estariam fora de sincronismo. O concentrador precisa ter algum subsídio para descobrir se os desvios acumularam acima do patamar tolerável, a fim de ordenar um novo zeramento.
Vou falar sobre o MCAP num outro artigo. Por ora, esclareço que o CSP é uma parte opcional do protocolo MCAP, que padroniza a sincronização de timestamps.
O truque do CSP é usar os dois tipos de clock (Bluetooth e civil), cada um no seu ponto forte. Não tem mágica, é algo que qualquer protocolo de aplicação pode implementar por sua conta; a única "vantagem" do CSP é estar descrito formalmente numa especificação.
Como o MCAP estabelece conexões entre duas partes, o CSP estabelece a um o papel de mestre e a outro o de escravo. No exemplo da esteira, o concentrador faria o papel de mestre em cada uma das conexões com os sensores-escravos.
O CSP resolve o problema da precisão adotando um timestamp relativo de 64 bits, em microssegundos. O mestre pode solicitar o zeramento do timestamp do escravo a qualquer tempo.
Do lado escravo, a implementação mais óbvia é anotar a hora deste zeramento, e depois calcular o timestamp relativo deduzindo a hora atual da hora anotada. A chamada gettimeofday() retorna a hora com precisão de microssegundos.
O problema da sincronização é resolvido com o auxílio do clock BT: o CSP permite que o mestre agende o reset do timestamp para um momento futuro, ou seja, quando o clock BT da piconet atingir determinado valor. Isto permite que o mestre resete o timestamp de todos os escravos "ao mesmo tempo", embora não agora e instantaneamente.
Cada escravo vai ter um hora civil ligeiramente diferente, e cedo ou tarde os timestamps vão desviar. Felizmente o CSP permite agendar o reset do timestamp para um valor específico (e não apenas zerá-lo), o que permite ao mestre fazer pequenas correções individuais.
O escravo pode ser configurado para enviar periodicamente amostras dos dois relógios (clock BT + timestamp). Como o clock BT é sincronizado, este anúncio periódico permite medir os desvios de timestamp entre diferentes escravos, e o mestre pode então tomar providências corretivas (como reajustar o timestamp de um escravo, ou mesmo resetar todos).
A transmissão da amostra evento + timestamp (quando por exemplo o objeto na esteira efetivamente passa pelo sensor ótico) é problema do protocolo de aplicação. O CSP apenas viabiliza a sincronização. O "protocolo de sensores de esteira" estaria definido num profile específico para este caso de uso.