quinta-feira, junho 25, 2009

Notícias Curtas de uma Manhã Chuvosa

Nesta manhã chuvosa em Sampa, enquanto crio coragem para começar mais um dia de trabalho, listo algumas notícias curtas mas interessantes.

Firmware Bloqueia Uso de Baterias Não Originais em Câmeras

Já escutei sobre esquemas de proteção para cartuchos e toners de impressora, mas para bateria de máquina fotográfica é novidade para mim. A Panasonic publicou atualizações de firmware que impedem o uso de baterias não originais, "para maior segurança aos usuários". E também aos acionistas.

Link: http://www.reghardware.co.uk/2009/06/25/panasonic_battery_drm/

Novo Anti-Virus Gratuito da Microsoft é Bom, Mas Download do Beta Está Suspenso

A Microsoft anunciou o beta de um novo anti-virus, o Security Essentials. As primeiras análises foram positivas; parece ser uma boa opção para quem está cansado dos paquidermes que viraram a maioria dos anti-virus e procura algo mais simples. Entretanto a Microsoft suspendeu o download um dia após o anúncio, provavelmente já satisfeita com a quantidade de downloads.

Links:
http://www.theregister.co.uk/2009/06/24/ms_morro_review/
http://www.theregister.co.uk/2009/06/24/mse_beta_halt/

Mais Uma Tecnologia Microsoft Para Usuários "Tarados"

Na semana passada eu brinquei que a Microsoft tinha achado um novo mercado com o tratamento de vídeos no Bing e com o modo InPrivate do IE8. O recurso DeepZoom do Silverlight também está atraindo os membros deste mercado.

Link (NSFW*): http://www.meiobit.com/meio-bit/miscelaneas/microsoft-deepzoom-versao-brasileira

Id Software Não é Mais Independente

A empresa Id Software (precisa mencionar os jogos dela?) foi vendida para uma distribuidora e deixa de ser o exemplo mais visível e bem sucedido de desenvolvedor independente. As duas empresas garantem que nada vai mudar, mas John Carmack trocou o seu tradicional tom técnico para algumas frases que lembram tirinhas do Dilbert:

"We will now be able to grow and extend all of our franchises under one roof, leveraging our capabilities across multiple teams while enabling forward looking research to be done in the service of all of them."

Link: http://www.theregister.co.uk/2009/06/24/id_software_sells_to_bethesda/


* NSFW = Not Safe For Work - contém imagens não apropriadas para o ambiente de trabalho. Ou na frente de crianças ingênuas.

quarta-feira, junho 24, 2009

Diploma Obrigatório

A polêmica em torno do fim da obrigatoriedade de diploma para os jornalistas reacende uma discussão mais abrangente: a importância ou não de um diploma para exercer uma determinada profissão.

É comum vermos nas discussões duas posições que eu classifico como enganos: a de que um diploma "dá direito" a um emprego e a de que certas profissões não requerem conhecimentos específicos. O primeiro engano é reforçado por instituições com interesses econômicos no assunto, como cursos preparatórios e faculdades. O segundo é um argumento usado por quem quer desmerecer uma profissão ou não está disposto ao esforço de preparação e está procurando um atalho.

O Que Um Diploma Não Garante

Para bem ou para o mal, obter um diploma atualmente pode ser um tarefa fácil. Com a proliferação das faculdades e cursos não presenciais, a disponibilidade de vagas está superando a procura em várias profissões, exorcizando o fantasma do vestibular.

Ao contrário que alguns apregoam, um diploma não é uma garantia de uma pessoa está apta a ser um bom profissional. Em muitos casos, nem mesmo confirma que a pessoa conseguiu absorver um mínimo do que foi (ou devia) ser ensinado. E é claro que existem muitos outros requisitos para ser um bom profissional, como experiência e ética.

O Que Uma Boa Faculdade Pode Fornecer

Embora não sejam poucos os casos de auto-didatas bem sucedidos, aprender uma profissão estudando sozinho não é trivial.

Em primeiro lugar, uma faculdade deve ter um currículo organizado de forma a colocar os estudos em uma ordem apropriada e com tempos proporcionais à importância e a dificuldade.

As boas faculdades costumam focar mais na base que nos detalhes. Isto prepara pessoas mais flexíveis porém requer um esforço delas para se preparar para a prática.

Bons professores vão ajudar a entender as partes mais complicadas e incentivar o estudo.

A faculdade pode também fornecer uma infraestrutura composta de laboratórios, bibliotecas, etc.

Por último, mas não menos importante, uma faculdade pode fornecer um ambiente propício ao estudo e à troca de informações com pessoas com o mesmo interesse.

O Que Um Diploma Pode Significar Para Quem Está Contratando

É claro que isto varia de pessoa a pessoa. Existem alguns que consideram um diploma um requisito essencial. Existem outros que dão um grande peso a diplomas de determinadas instituições (muitas vezes àquela em que ele próprio estudou).

Do meu ponto de vista, um diploma é um sinal que a pessoa teve o interesse e a oportunidade de aprender mais sobre a profissão pela qual se interessa. Para confirmar este sinal e que a oportunidade foi bem aproveitada é preciso olhar além do diploma.

Exemplos e Contra-Exemplos

Quase todos concordam que profissões como médico e engenheiro civil devem exigir diploma. Por outro lado, reconhecem que isto não elimina erros médicos nem construções inseguras.

Uma profissão que exige diploma é a de secretária. É bem provável que a maioria das "secretárias" que você conheça estejam registradas como "assistentes administrativas". Este "jeitinho" burla a exigência, mas a maioria destas "secretárias" não tem conhecimento das técnicas desta profissão.

Exigindo Mais Que Um Diploma

Para várias profissões existem Conselhos Regionais e o exercício da profissão está vinculado ao registro do profissional ao respectivo conselho. Na maioria dos casos o registro requer a apresentação do diploma, preenchimento de uma ficha e o pagamento de uma anuidade. Os conselhos tem a autoridade de cassar o registro dos maus profissionais, mas isto não é frequente.

A exceção mais conhecida são os advogados, que submetendo os candidatos a um exame. As taxas de reprovação costumam ser altas, reforçando a ideia que o diploma não assegura o conhecimento.

A Situação da Informática

A área de informática, talvez por ser relativamente nova, não tem maiores exigências nas suas profissões, sendo comum se encontrar pessoas com as diversas formações (e mesmo ausência de formação).

Se por um lado isto significa o livre acesso à área, por outro lado existe um número elevado de profissionais com conhecimentos deficientes, perpetuando mitos e produzindo trabalhos de baixa qualidade.

Concluindo

Acredito que a exigência de diploma para determinadas profissões não irá barrar profissionais ruins nem bons, já que ambos não terão dificuldades em obter um diploma. Inescrupulosos encontrarão maneiras de exercer a profissão ilegalmente, seja mentindo descaradamente, criando "nomes fantasia" para a profissão ou se escondendo por traz de um registro "de aluguel".

O que eu acho importante são duas coisas: a preocupação do profissional com o domínio das teorias e técnicas da sua profissão e a responsabilidade pelo trabalho produzido.

sexta-feira, junho 19, 2009

Observações Curtas de Sexta

Seguem abaixo algumas observações curtas sobre notícias que li esta semana.

Windows Seven sem IE na Europa

A notícia (ameaça?) de que a Microsoft vai lançar o Windows Seven na Europa sem o IE, continua causando alvoroço. A Opera Software, principal instigadora da investigação da UE sobre o bundling do IE no Windows, continua exigindo que durante a instalação o Windows apresente um menu com várias alternativas de navegador, o que a Microsoft considera o equivalente a exigir que a Coca Cola coloque uma lata de Pepsi nos seus six-pack.

Na minha opinião a gritaria reforça a posição da Microsoft de que os usuários esperam que um sistema operacional atual venha com um browser incluso.

Links:

http://www.channelregister.co.uk/2009/06/11/microsoft_windows_ie_sku_europe/
http://www.channelregister.co.uk/2009/06/15/jcxp_calls_for_opera_browser_boycott/

Opera "Reinventa" a Web

Após anunciar que ia reinventar a Web, a Opera anunciou o Opera Unite, que é uma junção de Web Server com Web Browser. O objetivo é permitir pessoas a compartilharem conteúdo de uma forma (quase) descentralizada.

Para mim (e para o The Register) parece ser um tentativa de contra-atacar os investimentos da Microsoft e Google na "Cloud Computing". Mas não me parece uma boa idéia termos milhares de web servers espalhados na mão de usuários que não querem nem sabem gerenciá-los. Nem ter toda esta infraestrutura amarrada por servidores da Opera (responsáveis pelo roteamento, já que a maioria das máquinas executando browsers não tem um IP fixo na internet).

Vamos ver também o que a RIAA vai falar sobre a funcionalidade decompartilhar música....

Link:

http://www.theregister.co.uk/2009/06/16/opera_unite/

Dias Difíceis para os Desenvolvedores para iPhone

O Worldwide Developers Conference da Apple gerou muitas notícias, particularmente o lançamento do iPhone 3GS. Entretanto nem tudo são flores: alguns desenvolvedores não estão nada satisfeitos com o tratamento dispensado pela Apple. Nos comentários no link abaixo, uma coisa rara hoje em dia: elogios para a Microsoft

Link:

http://www.osnews.com/story/21678/WWDC_quot_A_Giant_Middle_Finger_to_iPhone_Developers_quot_

Relacionado aos Dois Itens Anteriores?

Não é bom para as formigas ficarem no caminho dos elefantes. Da mesma forma, uma empresa pequena terá problemas se ficar no roadmap de uma maior. Fornecer um complemento para uma plataforma pode ser um negócio viável, mas pode ter vida curta.

Link:

http://www.joelonsoftware.com/items/2009/06/10c.html

Um Novo Mercado para Browsers e Buscadores?

Acidentalmente ou não, a Microsoft achou um "novo" mercado. Primeiro foi o modo InPrivate do IE8. Depois foi o modo como o Bing trata vídeos, o que permite burlar certos controles e restrições. Agora o Bing tem até um domínio específico para este "mercado alvo".

Link:

http://www.clicrbs.com.br/especial/rs/tecnologia/19,0,2547165,Microsoft-cria-dominio-de-buscas-especifico-para-pornografia.html


quarta-feira, junho 17, 2009

Sopke-o-dometer - Parte 11

Neste final da série vamos ver a lógica da aplicação em si. Temos três grandes partes: medir o tempo de uma volta da roda, calcular a velocidade correspondente e apresentar nos LEDs este resultado.

Medindo o Tempo de Uma Volta

A medição em si é simples: um contador (tickVolta) é zerado a cada começo de volta e incrementado pela interrupção periódica do timer. A parte mais complicada está em detectar o começo da volta, o que é feito pelo sensor de efeito Hall conectado ao ADC.

Como detalhei anteriormente, o ADC nos fornecerá um valor proporcional à proximidade do imã fixo ao quadro da bicicleta. Nos meus testes verifiquei um valor de 88 quando o sensor está longe do imã. Quando o sensor passa na frente do imã este valor aumenta ou diminui conforme o polo do imã que fica próximo do sensor.

Uma vez que o valor varia ligeiramente durante a passada, uso uma histerese (como detalhei aqui). O código abaixo faz a detecção:
    if (!bDetectou && ((medida > VPOS_1) || (medida < VNEG_1)))
{
// fim de uma volta
bDetectou = TRUE;

// pulando um trecho que explico depois...

tickVolta = 0;
P1OUT |= 1;
}
else
{
if (bDetectou && (medida < VPOS_2) && (medida > VNEG_2))
{
// pode procurar imã de novo
bDetectou = FALSE;
P1OUT &= 0xFE;
}
}
O teste (!bDetectou && ((medida > VPOS_1) || (medida < VNEG_1))) verifica se nos afastamos da referência num momento em que ainda não detectamos o imã, indicando o início da passagem.

Após a detecção do imã é preciso esperar o valor retornar para perto da referência antes de detectar uma outra passagem do imã: (bDetectou && (medida < VPOS_2) && (medida > VNEG_2)).

Cálculo da Velocidade

Esta parte é trivial, desde que se preste atenção às unidades de medida. A velociadade é distância dividida por tempo e queremos exibir o resultado final em Km/h, com uma casa decimal.

A constante CIRCUNF é a circunferência da roda (quanto ela anda em uma volta), medida em milímetros. A variável tickVolta indica quantos ticks de 100 microsegundos demorou a volta.

A velocidade em Km/s corresponde a (CIRCUNF/1000000)/(tickVolta/10000). Para obtermos em Km/h precisamos multiplicar por 3600 (número de segundos por hora). Por último vamos multiplicar por 10 para termos um casa decimal (mais precisamente, estamos medindo a velocidade em unidades de 0,1Km/h). Simplificando as potências de dez, ficamos com:
      // Calcula a velocidade em 0,1 Km/h
// veloc = distância / tempo
// CIRCUNF em mm, ticVolta em 100 us
// veloc = 3600 * (CIRCUNF / 100000) / (ticVolta / 10000)
veloc = (unsigned int) ((CIRCUNF*360L)/tickVolta);
Apresentação do Resultado

Para a apresentação do resultado, dividimos o tempo de uma volta em frames. Cada coluna de cada caracter do resultado será apresentada por um frame. Entre um caracter e outro teremos SPACE frames. A variável tickFrame contem quantos ticks dura cada frame; contFrame conta os ticks até o final do frame atual. Inicialmente contFrame contém a quantidade de ticks que precisam ser aguardados até a posição inicial da mensagem (escolhida para garantir a legibilidade da mensagem).

Uma dificuldade é que a apresentação é feita na volta seguinte a cada medição de velocidade. Se a bicicleta estiver acelerando ou freando a apresentação fica muito ruim. Após algumas tentativas mal sucedidas de compensar isto, acabei optando por não apresentar a mensagem quando ocorre uma mudança grande de velocidade entre duas voltas.

Dada a posição onde eu montei o Spoke-o-dometer e o sentido de rotação da roda, é necessário apresentar a mensagem do fim para o começo. Ou seja da última coluna do último caracter para a primeira coluna do primeiro caracter. Por este motivo a mensagem é montada em ordem contrária e a variável col é iniciada com 5.

Segue o resto do código que é executado quando a roda completa uma volta:
        // Calcula variação em relação à volta anterior
if (tickVolta > tickVoltaAnt)
delta = tickVolta - tickVoltaAnt;
else
delta = tickVoltaAnt - tickVolta;

// Só mostra velocidade se maior que 7.0 Km/h
// e não variou mais que 25%
if ((veloc > 70) && (delta < (tickVolta >> 2)))
tmsg = escreve_kmh(veloc, msg);
else
{
msg[0] = ' ';
msg[1] = 0;
tmsg = 1;
}
pMsg = &msg[0];

// Calcula o tempo por frame e a contagem para a posição inicial
tickFrame = tickVolta / NFRAMES;
contFrame = (tickVolta *(NFRAMES - POS_MSG - tmsg*(5+SPACE))) / NFRAMES;
tickVoltaAnt = tickVolta;
col = 5;
A formatação da mensagem é feita por uma conversão "caseira" do número binário em caracteres:
// Formata a velocidade para apresentação
// Mensagem é montada em ordem reversa
// "h/mk#,###"
int escreve_kmh (unsigned int vel, char *pv)
{
int tam = 7;

*pv++ = 'h';
*pv++ = '/';
*pv++ = 'm';
*pv++ = 'k';
*pv++ = '0' + (vel % 10); vel /= 10;
*pv++ = ',';
*pv++ = '0' + (vel % 10); vel /= 10;
if (vel != 0)
{
*pv++ = '0' + (vel % 10); vel /= 10;
tam++;
if (vel != 0)
{
*pv++ = '0' + (vel % 10);
tam++;
}
}
*pv = 0;
return tam;
}
O gerador de caracteres, que indica qual LED deve estar aceso em cada coluna de cada caracter está em uma matriz de bytes:
// Gerador de Caracteres
// Cada caracter corresponde a 5 bytes
// Cada byte corresponde a uma coluna
static const byte gc[16][5] =
{
0x7C, 0x82, 0x82, 0x82, 0x7C, // 0
0x02, 0x42, 0xFE, 0x02, 0x02, // 1
0x46, 0x8A, 0x92, 0xA2, 0x42, // 2
0x44, 0x82, 0x92, 0x92, 0x6C, // 3
0xF0, 0x10, 0x10, 0x10, 0xFE, // 4
0xF2, 0x92, 0x92, 0x92, 0x8C, // 5
0x6C, 0x92, 0x92, 0x92, 0x0C, // 6
0x80, 0x86, 0x98, 0xA0, 0xC0, // 7
0x6C, 0x92, 0x92, 0x92, 0x6C, // 8
0x60, 0x92, 0x92, 0x92, 0x6C, // 9
0x00, 0x00, 0x00, 0x00, 0x00, // SPACE (10)
0x00, 0x04, 0x06, 0x00, 0x00, // , (11)
0x7E, 0x08, 0x14, 0x22, 0x00, // k (12)
0x1E, 0x10, 0x0C, 0x10, 0x1E, // m (13)
0x03, 0x0C, 0x18, 0x30, 0x60, // / (14)
0x7E, 0x08, 0x08, 0x06, 0x00 // h (15)
};
Sobra apenas o trabalho de mudar os LEDs ao final de cada frame, na interrupção do timer:
                if (contFrame == 0)         // fim do frame atual
{
if (col > 0)
{
// vamos para a coluna anterior
col--;
valor = gc [char_index(*pMsg)][col];
P1OUT &= 0xC1;
P1OUT |= (valor & 0x3E);
P2OUT &= 0x3F;
P2OUT |= (valor & 0xC0);
contFrame = tickFrame;
}
else
{
// passar ao caracter seguinte
P1OUT = P1OUT & 0xC1;
P2OUT = P2OUT & 0x3F;
col = 5;
pMsg++;
if (*pMsg == 0)
tickFrame = 0; // fim da mensagem
else
contFrame = tickFrame * SPACE;
}
}
else
contFrame--;
A rotina char_index devolve o indice no gerador de caracteres para cada caracter:
/ c_index: retorna o índice do caractere na matriz gc
int char_index(char c)
{
if ((c - '0') >= 0 && (c - '0') < 10)
return (c - '0');
if (c == ' ') return CHAR_SPACE;
if (c == ',') return CHAR_COMMA;
if (c == 'k') return CHAR_K;
if (c == 'm') return CHAR_M;
if (c == '/') return CHAR_SLASH;
if (c == 'h') return CHAR_H;

//else (caractere estranho)
return CHAR_SLASH;
}

Com isto acredito ter coberto todo o código. Em caso de dúvida, o formulário de comentários está logo abaixo.

segunda-feira, junho 15, 2009

Spoke-o-dometer - Parte 10

Neste post vou explicar a parte do código do Spoke-o-dometer (SOD) relacionada à programação dos periféricos do microcontrolador. A documentação da Texas a respeito está disponível aqui em formato PDF. Sigo abaixo a mesma ordem que a documentação.

A maior dificuldade nesta programação está na grande quantidade de opções disponíveis. Para cada módulo do microcontrolador é necessário escolher a opção mais apropriada, ver quais as opções default após o reset e alterar os bits necessários nos registradores que controlam as opções.

Clock

O MSP430F2013 que estou usando permite usar até três fontes para o clock:
  • LFXT1CLK: clock de baixa frequência gerado por um cristal externo. Não usado no SOD.
  • VCLOCK: clock interno de 12KHz. Usei no início para gerar as interrupções de tempo; na versão final não é usado.
  • DCOCLK: clock interno de alta frequência. Programado para 8MHz no SOD.
Estas fontes podem ser conectadas a três sinais de clock que alimentarão o processador e os periféricos. Esta conexão pode ser direta ou através de um divisor. Os sinais de clock são:
  • MCLK: master clock, alimenta o processador. No nosso caso, é o SCOCLK (8MHz).
  • SMCLK: sub-main clock, é uma das alternativas de clock para os periféricos. No SOD o SMCLK é configurado para DCOCLK/8 (1MHz) e será usado para o timer e para o conversor analógico digital (ADC).
  • ACLK: clock auxiliar (normalmente de baixa frequência). No SOD é configurado para VCLOCK e era usado inicialmente com o timer. Na versão final não é usado.
Os clocks estão diretamente ligados ao consumo de energia. Quando o processador está rodando, todos os clocks estão ativos e o consumo é máximo. O processador pode ser colocado para dormir aguardando interrupções; o MCLK é desligado e os demais clocks podem ser desligados se não estiverem ligados aos periféricos que irão acordar o processador.

Nos testes iniciais eu estava usando um gerenciamento de energia mais sofisticado. O SMCLK só era mantido ligado com o processador dormindo quando o ADC estava ligado. Quando o ADC estava inativo somente ACLK ficava ligado, deixando o consumo muito próximo de zero.

Na versão final o timer está sendo alimentado pelo SMCLK portanto estou deixando SMCLK e ACLK sempre ligados.

A programação dos clocks é feita nas linhas abaixo:
   // Altera a configuração de clock para ativar o VLOCLK
BCSCTL3 |= LFXT1S1;

// SMCLK = MCLK / 8
BCSCTL2 = DIVS_3;

// Alimentação já deve estar estável, vamos ligar o DCO
BCSCTL1 = CALBC1_8MHZ;
DCOCTL = CALDCO_8MHZ;
A macro abaixo coloca o processador no modo 0 de economia de energia, no qual o processador fica parado mas os clocks SMCLK e ACLK ficam ligados:
    LPM0;             // Dorme tratando interrupção
O controle da economia de energia fica no registrador de status. Quando uma interrupção ocorre, este registrador é salvo na pilha e todos os clocks são ligados. Ao encerrar o tratamento de uma interrupção o registrador de status é restaurado da pilha; se nada especial for feito o processador volta a dormir no mesmo modo que estava antes. Isto é suficiente para a versão final do código.

Nas versões de teste, onde eu mudava dinamicamente de modo de economia de energia, era preciso usar as macros _BIC_SR_IRQ e _BIS_SR_IRQ para mudar a imagem do registrador na pilha.

E/S Digital

Esta parte é simples. o MSP430F2013 possui 10 pinos que podem ser usados para entrada e saída digital. Oito deles compõem o chamado P1 e dois deles o P2 (que usa somente os dois bits mais significativos).

Em P1 os bits 0 a 5 são programados para saída e correspondem a LEDs (o bit 0 é o LED verde na placa do processador; os demais são LEDs vermelhos do SOD). Os bits 6 e 7 são as entradas do ADC.

Em P2 os bits 6 e 7 são programados para saída e correspondem a LEDs do SOD.

A programação fica assim:

// Programa entradas e saídas
P1SEL = 0xC0; // P1.0 a P1.5 -> LEDs
// P1.6 e P1.7 são A3+ e A3-
P1DIR = 0x3F;
P1OUT = 0; // Todos as saídas em zero

P2SEL = 0; // Todos os pinos como I/O
P2DIR = 0xFF; // Todos os pinos como saída
P2OUT = 0; // Todos as saídas em zero

PxSEL indica quais pinos serão de E/S digital (bit em 1) e quais serão usados para funções especiais (bit em 0). PxDIR indica se o pino é de entrada (bit em 0) ou saída (bit em 1). PxOUT controla os pinos programados para saída digital.

Watchdog Timer

O WDT é uma segurança contra programas perdidos: quando ativo o software precisa periodicamente re-armá-lo para o processador não ser reiniciado. Após um reset o WDT é ligado; no SOD estamos simplesmente desligando-o:
    // Desliga Watchdog
WDTCTL = WDTPW + WDTSSEL + WDTHOLD;
Timer

O MSP430F2013 possui um timer bastante versátil. No SOD vamos usá-lo somente para gerar uma interrupção periódica.

Isto é feito colocando-o no up mode: o timer conta de zero até um valor final (inclusive), gera a interrupção e volta a contar a partir de zero.

Uso como clock para o timer o SMCLK (1MHz) e programo o valor final em 99. Desta forma, uma interrupção é gerada a cada 100 pulsos do clock, o que resulta em um intervalo de 100 micro-segundos:

// Valor para contar 100us c/ clock de 1MHz
#define TEMPO_100uS 99 // (100us * 1MHz) - 1

// Programar a interrupção de tempo real p/ cada 100us
TACCR0 = TEMPO_100uS;
TACTL = TASSEL_2 + MC_1 + TAIE; // SCLK, up mode, interrupt

A rotina de tratamento da interrupção deve ser marcada através do pragma vector=TIMERA1_VECTOR. O timer pode gerar interrupções por diversos motivos, o registrador TAIV informa qual. O que nos interessa é o overflow:
// Tratamento da interrupção do Timer A
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A_TO(void)
{
byte valor;

switch (TAIV)
{
case 10: // overflow
// nosso tratamento
break;

case 2: // CCR1, não utilizado
break;
}
}
Conversor Analógico Digital SD-16

Expliquei em detalhes o SD-16 na parte 5. A única alteração é que na versão final o DCO está a 8MHz mas o SMCLK continua sendo 1MHz. Em algumas versões intermediárias usei o SMCLK a 8MHz e programaei o SD-16 para dividí-lo por 8.

O código permanece assim:
    // Programa o ADC
// MSP430F2013 -> SD16
SD16CTL = SD16VMIDON + SD16REFON + SD16DIV_0 + SD16SSEL_1; // 1.2V ref, SMCLK
SD16INCTL0 = SD16INCH_3; // PGA = 1x, Diff inputs A3- & A3+
SD16CCTL0 = SD16SNGL + SD16UNI + SD16IE; // Single conversion, Unipolar, 256 SR, Int enable
SD16CTL &= ~SD16VMIDON; // VMID off: used to settle ref cap
SD16AE = SD16AE6 + SD16AE7; // P1.6 & P1.7: A3+/- SD16_A inputs
O SD16 é disparado de dentro da interrupção de tempo:
    if (!bAmostrando)
{
SD16CTL |= SD16REFON; // Liga a referência do SD16
SD16CCTL0 |= SD16SC; // Inicia uma conversão
bAmostrando = TRUE;
}

Quando a conversão é concluída, uma interrupção é gerada e o resultado está em SD16MEM0. Para economia de energia mantemos a referência ligada somente durante a conversão.
// Tratamento da interrupção do SD16
#pragma vector = SD16_VECTOR
__interrupt void SD16ISR(void)
{
unsigned int medida;

SD16CTL &= ~SD16REFON; // Desliga referência do SD16_A
medida = SD16MEM0 >> 8; // Pega medida (limpa IFG)
bAmostrando = FALSE; // Fim da amostragem

// trata a medida obtida
}
Embora o conversor forneça um resultado de 16 bits, usamos apenas os 8 mais significativos.


Com isto espero ter explicado toda a parte do código relacionada à programação dos periféricos do microcontrolador. No último post da série vou explicar a lógica do velocímetro.

sábado, junho 13, 2009

Spoke-o-dometer - Parte 9

Este post e os dois seguintes concluem esta série sobre um velocímetro que vai montado diretamente no aro da bicicleta e apresenta mensagens se valendo da persistência da visão. Neste post vou mostrar o hardware e o código final; no post seguinte vou explicar a programação dos periféricos do microcontrolador e no último explicar a lógica usada para calcular e apresentar a velocidade.

O Hardware

O projeto de hardware resistiu inalterado desde o começo. Repetindo o circuito (clique para ampliar):

A foto abaixo mostra a montagem:


O Software

Segue abaixo a listagem completa do software, que vou explicar nos post seguintes.

/*
Spoke-o-dometer
Teste 5 - Versão Completa

Daniel & Flávio Quadros - abril/junho, 2009
*/

#include <msp430.h>

// Constantes lógicas
#define FALSE 0
#define TRUE 1

// Tipo byte
typedef unsigned char byte;

// Circunferência aprox. da roda em milimetros
#define CIRCUNF 2090L

// Valor para contar 100us c/ clock de 1MHz
#define TEMPO_100uS 99 // (100us * 1MHz) - 1

// Gerador de Caracteres
// Cada caracter corresponde a 5 bytes
// Cada byte corresponde a uma coluna
static const byte gc[16][5] =
{
0x7C, 0x82, 0x82, 0x82, 0x7C, // 0
0x02, 0x42, 0xFE, 0x02, 0x02, // 1
0x46, 0x8A, 0x92, 0xA2, 0x42, // 2
0x44, 0x82, 0x92, 0x92, 0x6C, // 3
0xF0, 0x10, 0x10, 0x10, 0xFE, // 4
0xF2, 0x92, 0x92, 0x92, 0x8C, // 5
0x6C, 0x92, 0x92, 0x92, 0x0C, // 6
0x80, 0x86, 0x98, 0xA0, 0xC0, // 7
0x6C, 0x92, 0x92, 0x92, 0x6C, // 8
0x60, 0x92, 0x92, 0x92, 0x6C, // 9
0x00, 0x00, 0x00, 0x00, 0x00, // SPACE (10)
0x00, 0x04, 0x06, 0x00, 0x00, // , (11)
0x7E, 0x08, 0x14, 0x22, 0x00, // k (12)
0x1E, 0x10, 0x0C, 0x10, 0x1E, // m (13)
0x03, 0x0C, 0x18, 0x30, 0x60, // / (14)
0x7E, 0x08, 0x08, 0x06, 0x00 // h (15)
};

#define CHAR_SPACE 10;
#define CHAR_COMMA 11;
#define CHAR_K 12;
#define CHAR_M 13;
#define CHAR_SLASH 14;
#define CHAR_H 15;


// Limites para detectar passagem pelo ímã
#define VREPOUSO 88 // 01011000
#define VPOS_1 120 // 01111000
#define VPOS_2 100 // 01111000
#define VNEG_1 56 // 00111000
#define VNEG_2 76 // 00111000

static byte bAmostrando = FALSE; // TRUE enquanto aguarda ADC
static byte bDetectou = FALSE; // TRUE qdo detecta o imã


// Contagem do tempo de uma volta e
// controle da escrita da mensagem

#define NFRAMES 360 // frames por volta
#define POS_MSG 45 // inicio da mensagem
#define SPACE 3 // frames de espaço entre letras

static unsigned long tickVolta; // número de ticks em uma volta
static unsigned long tickVoltaAnt; // número de ticks da volta anterior
static unsigned long tickFrame = 0; // número de ticks por frame
static unsigned long contFrame; // ticks até o próximo frame
static byte col; // coluna sendo apresentada
static char *pMsg; // caracter sendo apresentado
static char msg[16]; // mensagem a apresentar

// Rotinas locais
int escreve_kmh (unsigned int vel, char *pv);
int char_index (char c);

// Programa Principal
void main (void)
{
unsigned int cont = 0;

// Desliga Watchdog
WDTCTL = WDTPW + WDTSSEL + WDTHOLD;

// Altera a configuração de clock para ativar o VLOCLK
BCSCTL3 |= LFXT1S1;

// SMCLK = MCLK / 8
BCSCTL2 = DIVS_3;

// Programa entradas e saídas
P1SEL = 0xC0; // P1.0 a P1.5 -> LEDs
// P1.6 e P1.7 são A3+ e A3-
P1DIR = 0x3F;
P1OUT = 0; // Todos as saídas em zero

P2SEL = 0; // Todos os pinos como I/O
P2DIR = 0xFF; // Todos os pinos como saída
P2OUT = 0; // Todos as saídas em zero

// Programa o ADC
// MSP430F2013 -> SD16
SD16CTL = SD16VMIDON + SD16REFON + SD16DIV_0 + SD16SSEL_1; // 1.2V ref, SMCLK
SD16INCTL0 = SD16INCH_3; // PGA = 1x, Diff inputs A3- & A3+
SD16CCTL0 = SD16SNGL + SD16UNI + SD16IE; // Single conversion, Unipolar, 256 SR, Int enable
SD16CTL &= ~SD16VMIDON; // VMID off: used to settle ref cap
SD16AE = SD16AE6 + SD16AE7; // P1.6 & P1.7: A3+/- SD16_A inputs

// Dá um tempinho para estabilizar a alimentação
while (cont < 0xFF)
cont++;
cont = 0;

// Alimentação já deve estar estável, vamos ligar o DCO
BCSCTL1 = CALBC1_8MHZ;
DCOCTL = CALDCO_8MHZ;

// Programar a interrupção de tempo real p/ cada 100us
TACCR0 = TEMPO_100uS;
TACTL = TASSEL_2 + MC_1 + TAIE; // SCLK, up mode, interrupt

// O nosso programa principal vai ficar dormindo,
// todo o tratamento será feito na interrupção
_BIS_SR(GIE);
LPM0; // Dorme tratando interrupção

// Nuca vai chegar aqui
while (1)
;
}

// Tratamento da interrupção do Timer A
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A_TO(void)
{
byte valor;

switch (TAIV)
{
case 10: // overflow
tickVolta++; // mais um tick na volta atual
if (tickFrame != 0)
{
if (contFrame == 0) // fim do frame atual
{
if (col > 0)
{
// vamos para a coluna anterior
col--;
valor = gc [char_index(*pMsg)][col];
P1OUT &= 0xC1;
P1OUT |= (valor & 0x3E);
P2OUT &= 0x3F;
P2OUT |= (valor & 0xC0);
contFrame = tickFrame;
}
else
{
// passar ao caracter seguinte
P1OUT = P1OUT & 0xC1;
P2OUT = P2OUT & 0x3F;
col = 5;
pMsg++;
if (*pMsg == 0)
tickFrame = 0; // fim da mensagem
else
contFrame = tickFrame * SPACE;
}
}
else
contFrame--;
}
if (!bAmostrando)
{
SD16CTL |= SD16REFON; // Liga a referência do SD16
SD16CCTL0 |= SD16SC; // Inicia uma conversão
bAmostrando = TRUE;
}
break;

case 2: // CCR1, não utilizado
break;
}
}

// Tratamento da interrupção do SD16
#pragma vector = SD16_VECTOR
__interrupt void SD16ISR(void)
{
unsigned int medida;
unsigned int veloc;
unsigned long delta;
int tmsg;

SD16CTL &= ~SD16REFON; // Desliga referência do SD16_A
medida = SD16MEM0 >> 8; // Pega medida (limpa IFG)
bAmostrando = FALSE; // Fim da amostragem

if (!bDetectou && ((medida > VPOS_1) || (medida < VNEG_1)))
{
// fim de uma volta
bDetectou = TRUE;

// Calcula variação em relação à volta anterior
if (tickVolta > tickVoltaAnt)
delta = tickVolta - tickVoltaAnt;
else
delta = tickVoltaAnt - tickVolta;

// Calcula a velocidade em 0,1 Km/h
// veloc = distância / tempo
// CIRCUNF em mm, ticVolta em 100 us
// veloc = 3600 * (CIRCUNF / 100000) / (ticVolta / 10000)
veloc = (unsigned int) ((CIRCUNF*360L)/tickVolta);

// Só mostra velocidade se maior que 7.0 Km/h
// e não variou mais que 25%
if ((veloc > 70) && (delta < (tickVolta >> 2)))
tmsg = escreve_kmh(veloc, msg);
else
{
msg[0] = ' ';
msg[1] = 0;
tmsg = 1;
}
pMsg = &msg[0];

// Calcula o tempo por frame e a contagem para a posição inicial
tickFrame = tickVolta / NFRAMES;
contFrame = (tickVolta *(NFRAMES - POS_MSG - tmsg*(5+SPACE))) / NFRAMES;
tickVoltaAnt = tickVolta;
tickVolta = 0;
col = 5;
P1OUT |= 1;
}
else
{
if (bDetectou && (medida < VPOS_2) && (medida > VNEG_2))
{
// pode procurar imã de novo
bDetectou = FALSE;
P1OUT &= 0xFE;
}
}
}

// Formata a velocidade para apresentação
// Mensagem é montada em ordem reversa
// "h/mk#,###"
int escreve_kmh (unsigned int vel, char *pv)
{
int tam = 7;

*pv++ = 'h';
*pv++ = '/';
*pv++ = 'm';
*pv++ = 'k';
*pv++ = '0' + (vel % 10); vel /= 10;
*pv++ = ',';
*pv++ = '0' + (vel % 10); vel /= 10;
if (vel != 0)
{
*pv++ = '0' + (vel % 10); vel /= 10;
tam++;
if (vel != 0)
{
*pv++ = '0' + (vel % 10);
tam++;
}
}
*pv = 0;
return tam;
}

// c_index: retorna o índice do caractere na matriz gc
int char_index(char c)
{
if ((c - '0') >= 0 && (c - '0') < 10)
return (c - '0');
if (c == ' ') return CHAR_SPACE;
if (c == ',') return CHAR_COMMA;
if (c == 'k') return CHAR_K;
if (c == 'm') return CHAR_M;
if (c == '/') return CHAR_SLASH;
if (c == 'h') return CHAR_H;

//else (caractere estranho)
return CHAR_SLASH;
}
O Resultado

O vídeo abaixo mostra o Spoke-o-dometer em funcionamento:

sexta-feira, junho 12, 2009

Música na Wikipedia e YouTube

Peguei a mania de ao escutar música no micro sair procurando o artista ou a música no Wikipedia e no YouTube.

Normalmente a Wikipedia possui uma boa biografia de músicos e bandas. A quantidade de informações sobre álbuns varia bastante. Páginas para músicas específicas são mais raras e poucas contem informação relevante.

O YouTube é bastante divertido. Apesar da qualidade dos vídeos ser baixa na maioria dos casos, dá para encontrar uma quantidade imensa de curiosidades (pelo menos enquanto os donos dos direitos autorais não partirem para a briga). No meu Firefox tenho o YouTube na lista de buscadores e a extensão DownloadHelper para salvar os vídeos.

Comecei a usar recentemente o "tocador" aTunes que apresenta informações sobre o artista obtidas na Last.Fm e vídeos relacionados no YouTube. Futuramente faço uma crítica mais completa deste software.

Aqui seguem os links para algumas curiosidades que achei no YouTube:

Genesis - Rock Progressivo
Peter, Paul and Mary - Folk
Roling Stones
  • Paint It Black, data ignorada mas com a banda bem novinha e com Brian Jones
Diana Krall - Jazz & Blues
  • Crazy, com o maridão Elvis Costello e a figuraça Willie Nelson.
Allman Brothers - Southern Rock
O YouTube é também um bom lugar para quem quer aprender a tocar:
E guardei para o fim uma pequena joia. A banda Focus era bem conhecida na minha juventude, particularmente o álbum Moving Waves que contem a indescritível Hocus Pocus. Para ouvir nas caixas, não no fone de ouvido.

Editado às 10:15: problemas de formatação no final do texto, que não aparecem no editor do Blogger. O motivo eram uns tags <span>. Já não basta os problemas com spam, agora tenho que me preocupar com span!

Editado novamente em 11/nov/09: corrigido um erro no texto e acertado o parágrafo anterior (pois o editor do Blogger considerou o tag span literalmente).

quarta-feira, junho 10, 2009

Spoke-o-dometer - Parte 8

Tendo passado mais de um mês desde o post anterior da série, me parece apropriado dar alguma notícia. Mais que o bug no compilador, falta de tempo e foco é o que impediu de concluir este projeto.

O meu filho avançou no código, colocando o cálculo e a apresentação da velocidade em km/h. Durante esta mexida dele, deu para perceber algumas limitações e erros do código apresentado anteriormente.

O código é movido a uma interrupção periódica de timer, que era gerada a partir de um clock interno de 12KHz. O primeiro problema é que eu estava calculando errado o valor de contagem (TEMPO_xxx). Após detectar divergência com uma leitura de velocidade na base do cronometro, revi com atenção a documentação do MSP430 e percebi que ele conta um a mais que o valor programado. Assim, uma contagem de 6 gera uma temporização de 583 useg ao invés de 500 useg.

Um problema mais crítico é que à medida que a velocidade sobe temos menos ticks por volta. Na hora de dividir a volta em "frames" a imprecisão aumenta, fazendo a largura dos caracteres variarem. A solução para isto vai ser usar um clock mais alto; isto aumentará o consumo do circuito mas dará uma precisão muito maior. Isto exige rever a programação do hardware e fazer alguns cálculos para garantir que os números vão caber nas variáveis.

Por último, estou usando o tempo de uma volta para apresentar a mensagem na volta seguinte, o que causa problemas quando estamos acelerando ou freando. Para melhorar isto pretendo considerar também a variação de tempos de uma volta para outra.

Tudo isto exige algum estudo, mexidas no código e testes. Estou contando com o feriado desta semana para chegar a uma versão "final", que vou publicar junto com uma tentativa mais decente de explicar o funcionamento do código.

terça-feira, junho 09, 2009

SDL Game Contest

Ainda na linha de competições de desenvolvimento de jogos, segue o link para uma competição de desenvolvimento de um "side-scrolling shooter" em C, C++ ou Delphi*, usando SDL:

http://www.sdltutorials.com/contest/

O prazo é até 1o de setembro de 2009 e o 1o prêmio é de US$200.

O organizador sugere como inspiração o jogo R-Type.

Fonte: GameDev.net

* ver os comentários após o anúncio.

sábado, junho 06, 2009

15a Competição Anual de Ficção Interativa

Para quem quiser se arriscar a escrever uma aventura curta, o site da competição deste ano já está no ar: http://www.ifcomp.org.

As ferramentas mais usadas para escrever uma aventura (todas grátis) são:
Você pode também criar a sua própria ferramenta!

sexta-feira, junho 05, 2009

Últimas Notícias

Versão on-line de jornal invadida pela gang dos nulls:

terça-feira, junho 02, 2009

A Volta da Ilha do Macaco

Quando se fala em jogos de Aventura, AIlha do Macaco é sem dúvida um clássico. O criador da Ilha do Macaco, Ron Gilbert, colocou no seu blog uma lista de comentários e curiosidades sobre o jogo. Mais interessante ainda anunciou que:

domingo, maio 31, 2009

Livro de Maio: Tintin - The Complete Companion

As aventuras de Tintim encantam pessoas desde 1929. Em "Tintin - The Complete Companion", Michael Farr disseca um a um os álbuns escritos por Hergé, descrevendo as fontes das imagens no mundo real, as condições em que eles foram escritos e algumas curiosidades.



Um livro de porte

A Amazon (como as demais livrarias virtuais) apresenta as imagens das capas "chapadas" (vista frontal perpendicular) e com tamanho normalizado. Isto tem me trazido várias surpresas, uma vez que não costumo prestar atenção aos dados de dimensão e número de páginas. The Complete Companion é um exemplo disto. É um livro de páginas grandes, um pouco maior que uma folha A4 ou que um álbum do Tintim, com capa dura (coberta por uma sobrecapa) e 200 páginas. Como merece o assunto, possui uma quantidade muito grande de ilustrações (ocupando mais de metade do espaço das páginas), grande parte colorida.

A qualidade é bastante inesperada para um livro com preço de US$20 .

Uma abordagem muito completa

O livro aborda os 24 álbuns disponíveis, de "Tintim no País dos Sovietes" (que Hergé descartou posteriormente como uma tolice de juventude) a "Tintim e a Alfa-Arte" (incompleto e publicado após a morte de Hergé).

Embora não se trate de uma biografia (que o autor escreveu posteriormente), é apresentado um resumo da situação de Hergé quando da escrita de cada álbum.

São também discutidas as diferenças entre as publicações seriadas (inicialmente no Le Vingtième Siècle, depois no Le Soir e finalmente na Revista Tintin) e as várias edições dos álbuns (inclusive diferenças de nomes entre as versões belgas e inglesas).

O mais interessante, entretanto, são as comparações entre os desenhos dos álbuns e as imagens ou fotos que os inspiraram. O detalhismo e a preocupação com a realidade sempre foram uma marca registrada de Tintim e o livro mostra os extremos a que Hergé foi para garantir isto.

Polêmicas

Hergé e Tintim não escaparam de algumas polêmicas ao longo dos anos, que o livro aborda com detalhes.

comentei a crítica ingênua e estereotipada ao comunismo em "Tintim no País dos Sovietes". Os dois livros seguintes, "Tintim no Congo" e "Tintim na América", foram criticados por terem um visão colonialista e racista. Por exemplo, em "Tintim no Congo" Tintim dá uma aula de geografia falando sobre "a pátria de vocês: a Bélgica!". Por outro lado, as pessoas supostamente vítimas deste racismo sempre manifestaram seu gosto por Tintim. Mais ironicamente ainda, quando os álbuns foram publicados nos EUA as editoras exigiram que fossem alteradas cenas que mostravam brancos e negros juntos.

Na época destes álbuns Hergé trabalhava no Le Vingtième Siècle que tinha uma linha bastante conservadora. Com a invasão da Bélgica pela Alemanha durante a Segunda Guerra, o Le Vingtième Siècle foi fechado. Hergé foi então trabalhar no Le Soir, que se comportava como um jornal oficial dos alemães. Isto rendeu-lhe a acusação de colaborador (e até de nazista) após a derrota dos alemães.

Novamente a censura foi irônica: "Tintim na América" e "A Ilha Negra" foram censurados pelos alemães por conter referências aos EUA (na verdade não exatamente elogiosas) e à Inglaterra, porém "O Cetro de Ottokar" foi liberado apesar de ser uma crítica nada velada à política expansionista dos alemães no pré-guerra. Outros álbuns anteriores eram também críticos ao imperalismo do "eixo": "O Loto Azul" critica o Japão e na "A Ilha Negra" o vilão é um alemão imprimindo notas falsas para enfraquecer a Inglaterra. A invasão da Bélgica obrigou Hergé a interromper "Tintim no País do Ouro Negro" que tinha como trama um plano alemão de sabotar os combustíveis para enfraquecer os demais países europeus.

Em "Perdidos no Mar" Hergé denuncia a exploração e escravidão dos negros africanos, porém viu-se atacado pelo fato dos negros serem apresentados falando um fancês cheio de erros.

Veredito

Se você é fã de Tintim e tem fluência em inglês, recomendo fortemente este livro. Ele dará uma dimensão a mais aos álbuns, revelando detalhes e colocando-os em um contexto maior. E o deixará de queixo caído ao comparar os desenhos com as fotos que os inspiraram.

sábado, maio 30, 2009

Jogo do Mês: Duke Nukem Manhattan Project

Aproveitando o rebuliço causado pelo cancelamento de Duke Nukem Forever, o site Good Old Games (que eu comentei aqui) está com uma promoção até 1 de Junho: Duke Nukem 3D: Atomic Edition + Duke Nukem Manhattan Project por US$8.98.

Embora eu ainda tenha o meu antigo Atomic Edition, estas versões tem a vantagem de estarem para rodar no Vista e não terem proteção contra cópia (ou seja, não precisa deixar o CD no drive, dá para fazer backup, etc). O Manhattan Project eu conhecia de nome, mas nunca tinha jogado.

O Manhattan Project (MP) está agora comendo as minhas noites. É um jogo do tipo "plataforma", onde o jogador se movimenta sobre uma superfície, correndo e pulando. Este tipo de jogo é inerentemente 2D, porém o MP possui uma apresentação 3D com o jogador limitado a um caminho fixo. O resultado é visualmente muito bom e aumenta a imersão no jogo (chega a dar medo quando você está pulando de um andaime para outro no alto de um prédio).


Como é de se esperar (é Duke Nukem, certo?) o jogo tem uma boa quantidade de sangue (mas nada assustador) e algumas mulheres seminuas (mas não chega perto ao que você vê numa banca de jornal - e eu não estou nem mesmo me referindo a revistas pornô). O palavreado do Duke é meio chulo, mas quem não soltaria um ou outro palavrão quando mutantes estão metendo bala em você?

As armas e acessórios não são originais, mas continua sendo divertido usar as pipe bombs e o jetpack.

O GOG fornece ainda alguns extras como um conjunto de MP3 com as falas do Duke e dos vilões e alguns efeitos especiais. Ótimo para quem quer um ringtone realmente de arrepiar.

Veredito: realmente uma pechincha. Mesmo se você estiver lendo isto depois que a promoção acabou, vale tranquilamente o preço normal.

quinta-feira, maio 28, 2009

Impressora 3D para Doces

Uma das tecnologias que mais me impressiona são as impressoras 3D. Basicamente estamos falando de uma impressora capaz de imprimir sólidos.

E não estamos falando de ficção científica: a tecnologia já está disponível para uso até mesmo aqui no Brasil. tem máquinas à venda nos EUA por preços inferiores ao que se pagava pelas primeiras impressoras laser nos anos 80. Por enquanto a aplicação principal é fazer protótipos em plástico, mas já tem gente pensando em fazer prédios.

Tem até um projeto open-source de impressora 3D. Esta previsto até mesmo a capacidade de auto-reprodução (isto é, conseguir fabricar nela própria as partes necessárias para montar uma máquina igual).

Mas a máquina descrita aqui realmente me impressionou: uma impressora 3D que trabalha com açucar (e montada por hobbistas):


PS: Descoberto a partir do feed do Evil Mad Scientist, um site muito doido que eu comecei a acessar recentemente e está me dando boas idéias para projetos eletrônicos futuros.

quarta-feira, maio 27, 2009

Porque a Microsoft tem tantas versões do Windows Vista e Seven?

Uma das coisas confusas e irritantes do Windows Vista, e que deverá ser mantida no Windows Seven, é a quantidade absurda de versões. Qual o motivo disto?

A razão é um dos conceitos mais poderosos e perigosos do Marketing: a segmentação. Uma boa explicação disto, e outros fatores de precificação de software, está neste artigo clássico de Joel Spolsky (em inglês). O que segue abaixo é a minha tentativa de explicação (em português).

Tipicamente a quantidade de cópias que se espera vender de um software tem uma relação direta com o preço: quanto menor o preço mais pessoas irão comprar. Obs.: enfase no tipicamente; existem muitos outros fatores em jogo, como a associação de preço a qualidade.

Inciando o meu exemplo hipotético, vamos supor que o potencial de venda (número de cópias) de um determinado software varie da seguinte forma com o preço:

Em outras palavras, se eu fixar um preço de R$500, vou vender apenas duzentas cópias; se baixar o preço para R$100,00 venderei 1500 cópias.

Mais importante que o número de cópias é o lucro que eu terei. Continuando as minhas hipóteses, vamos supor que eu tenha tido um custo fixo de R$50.000,00 para desenvolver o software e que eu tenha um custo variável de R$30 por cópia vendida. Alguns minutos mexendo na planilha e chegamos ao seguinte resultado:

Aha! O preço de R$300 maximiza o meu lucro! Apesar do faturamento ser o mesmo que com preços de R$100 e R$200, nestes dois casos o lucro por cópia é tão mais baixo que o lucro total fica menor.

Hora de imprimir as etiquetas de preço... Mas a nossa vista não consegue fugir da primeira tabela. Em um extremo, temos 200 pessoas que estariam dispostas a pagar R$500; vendendo por R$300 estamos "perdendo" R$40.000! Na outra ponta, temos 1000 pessoas estão deixando de comprar o software por achar caro.

E aí surge a idéia da segmentação: vamos criar três versões, a Lite, Standard e Pro e vendê-las, respectivamente, por R$ 100, 300 e 500. Chegamos à planilha "matadora":

Por um momento se imagine apresentando esta tabela em uma reunião de diretoria. Você será aclamado como um gênio! Maximizou o lucro e a quantidade de cópias. Vai ganhar uma sala, um aumento e até a chave do banheiro da diretoria1! Talvez o presidente da firma até fale para a gatinha da filha2 dele prestar mais atenção naquele rapaz esperto.

Entretanto, o diretor financeiro (que é bom de números), sugere: "porque não criarmos também versões a R$200 e R$400"? Ao que o diretor comercial sai com a sugestão definitiva: "Vamos abolir a lista de preços e vender o produto pelo máximo que o cliente estiver disposto a pagar"! Ops...

Hora de acordar, lavar a cara com água fria e voltar à dura realidade do mundo real. Clientes não são números que podem ser movidos de uma coluna para outra (apesar de muita gente insistir o contrário). Os clientes vão comparar as opções independente de quanto estão dispostos a gastar. Se você esconder as opções no momento da venda, o cliente acabará descobrindo depois e vai ficar ainda mais bravo. O cliente que optou pela versão Lite vai reclamar que aquela "pequena coisinha essencial" só está disponível na versão Pro (que custa 5x mais). O cliente que comprou a versão Pro vai sentir-se enganado ao descobrir que suas necessidades são atendidas pela versão Standard que custa "quase a metade do preço". E é claro que é preciso uma campanha para educar vendedores e clientes sobre as diferenças entre as versões.

O segredo do sucesso de uma estratégia de segmentação está na diversificação das versões, na percepção de valor comparada aos preços e à percepção dos custos.

O cliente não vai gostar se achar que está sendo feita uma segmentação "forçada". Colocar um componente adicional em uma impressora para ela ficar mais lenta e ser vendida como um modelo mais barato não rola. Fabricar osciloscópios digitais com "x" megabytes de memória, bloquear metade disso e vendar a senha para liberar não rola. Limitar o tamanho da tela do computador que vai rodar uma versão do sistema operacional, vai rolar?

Por outro lado, existem inúmeros exemplos de segmentação bem sucedida, tanto com software como com outros produtos. A indústria automobilística trabalha exclusivamente assim (o engenheiro que propos as "16 válvulas" deve ter ganhado a chave do banheiro).

Concluíndo: o Windows Vista e o Windows Seven tem um monte de versões porque a Microsoft escutou e seguiu o conselho do diretor financeiro. E não escuta os protestos dos seus clientes.

Notas:

1Típica referência americana. Alguém sabe se isto é símbolo de status aqui no Brasil?

2As leitoras sintam-se à vontade de substituir "gatinha" e "filho" por "gatão" e "filho". Ou o que for da sua preferência.

quarta-feira, maio 20, 2009

Segurança é problema somente dos usuários Windows?

A Microsoft está definitivamente manchada pelos vários problemas de segurança nos seus produtos e para muitos Windows é sinônimo de vulnerabilidade. Usuários de outras plataformas às vezes leem esta afirmação na ordem contrária (vulnerabilidade = Windows) e vivem num estado de falsa segurança.

Topei hoje com um artigo do The Register que ilustra como problemas de vulnerabilidade estão presentes também na plataforma Mac:

http://www.theregister.co.uk/2009/05/19/unpatched_apple_vulnerability/

Resumindo o artigo, a Sun detectou há seis meses uma vulnerabilidade na JVM que a Apple ainda não corrigiu, apesar de ter liberado updates e novas versões do MacOS neste período. Quem quiser que vare a noite tentando entender porque a Apple precisa corrigir um problema da Sun, mas o fato é que a vulnerabilidade está lá.

É interessante também olhar os links em Related stories:

http://www.theregister.co.uk/2009/05/06/browser_update_study/

Um estudo de logs do Google observou que os usuários de Safari e Opera demoram mais para atualizar as suas versões. Os autores do estudo atribuem isto ao fato destes browsers não serem tão agressivos quanto o Firefox e Chrome no oferecimento de atualizações. Obs: o IE não entrou no estudo porque não revela o número completo da versão.

http://www.theregister.co.uk/2009/03/03/safari_at_pwn2own/

Na véspera de um concurso de hacking (em março), um veterano da edição anterior aponta o Safari como uma presa fácil e chega a dizer pelo menos uma das barreiras anti-hacking está atualmente melhor na plataforma Windows.

http://www.theregister.co.uk/2009/03/19/pwn2own_day1/

E efetivamente em questão de horas um competidor derrubou o Safari, Firefox e IE na competição. Pelo menos ele achou que está bem mais difícil quebrar browser agora que há alguns anos.

http://www.theregister.co.uk/2009/04/16/new_ibotnet_analysis/

Para fechar, notícias de uma botnet de Macs, cortesia de trojans incluídos em cópias piratas do iWork e Photoshop, e a afirmação de especialistas que os ganhos de mercado da Apple atraíram as atenções dos autores de malware.

CONSTANT VIGILANCE!

terça-feira, maio 19, 2009

Compilador Erra!

Completando as informações do meu post sobre um código estranho gerado pelo compilador IAR para o microcontrolador MS430, seguem o resultado de alguns testes adicionais e a comprovação que era realmente um bug do compilador.

Ainda utilizando a versão 4.11B do compilador, experimentei mudar o nível de otimização (o default é Low). Praticamente não fez diferença, exceto pela troca de CLRC + RRC.B por RRA.W nos níveis mais altos de otimização. Aliás, se tem uma sequência melhor para fazer uma operação não vejo porque não usá-la sempre; este mudança não parece estar ligada às opções ligadas no nível seguinte (commom subexpression optimization e code motion).

Parti então para a instalação da versão mais recente (4.20.1). Um ponto positivo é que cada versão instala por padrão em um diretório diferente e elas parecem conviver sem problemas. Esta versão gerou o mesmo código que a versão antiga (3.42A).

Passando um pente fino nos Release Notes da 4.20.1, encontrei na lista de correções:

EW20239: Incorrect code could sometimes be generated when accessing parts of volatile objects. Instead of accessing all bits in the object part, the code would only access a single bit. Typically, this would occur when using volatile in combination with bitfields.

O registrador P1OUT é realmente volatile e o código estava acessando um bit ao invés de todos, apesar de eu não estar usando bitfields mas sim constantes explícitas. Portanto acho que o meu problema se encaixa nesta correção.

Fica a preocupação de um bug destes, que envolve uma operação que considero comum, ter passado pelos testes e ter ido a campo.

segunda-feira, maio 18, 2009

Mentiras, Grandes Mentiras e a Interpretação de Gráficos

Esta na minha lista, há um bom tempo, um post falando sobre como usar e como não usar gráficos. Infelizmente, ainda não aprendi o suficiente para isto. O que não me impede de criticar as conclusões destacadas pelo Estadão com relação a um gráfico de criação de empregos formais nos últimos meses (clique para ampliar):

Reparar como o texto destaca "terceiro mês de crescimento" e que a "geração de vagas em abril foi três vezes maior que em março" e convenientemente ignora aquele "pequeno" pulso negativo de dezembro e os dados próximos a constante na primeira metade do gráfico.

Na minha opinião, uma manchete mais realista seria "nível de empregos continua recuperação após baque do fim de ano, mas ainda é metade da média de antes da crise".

sábado, maio 16, 2009

Watchmen (Graphic Novel) - Crítica

Há muito tempo que escuto falar deste marco das história em quadrinhos - Watchmen. Com o lançamento do filme decidi que era hora de finalmente lê-lo (acabei demorando demais e o filme já está saindo de cartaz). Apesar de terem sido lançadas edições em português, preferi comprar uma edição americana para ter o texto original.


Segundo as informações na Livraria Cultura, esta edição de 2008 contém páginas restauradas com ajuda do colorista original. Embora seja uma brochura ("capa mole" e encadernação por cola) o material das páginas é bom (mas não excelente).

A Arte

Os desenhos são bastante bons, mas não de "babar" (como o incrível "Marvels"). Um ponto alto é a composição das páginas, baseada em um grid de nove painéis.

Na minha opinião a arte transmite bem a história, sem roubar as atenções.

A História

Não vou entrar em detalhes para não tirar as surpresas de quem ainda não leu, quem quiser tem tudo descrito na Wikipedia. A narrativa se passa em uma história alternativa, na qual a presença dos super-heróis mudou de forma significativa a história dos EUA (que ganham a Guerra do Vietnã) e afetou o equilíbrio de forças entre EUA e URSS. É bom lembrar que as revistas foram publicadas originalmente em 1986 e 1987 época em que ainda existia uma forte preocupação com a Guerra Fria e um risco muito maior de uma guerra nuclear. Parte desta temática pode parecer "aguada" para os leitores atuais.

O termo super-heróis me parece um pouco inadequado, já que apenas um deles possui "super-poderes"; os demais contam apenas com preparo físico e inteligência. Na época da história, os "super-heróis" estão proibidos, exceto os que trabalham diretamente sob a supervisão do governo. Os demais ou se aposentaram ou atuam na clandestinidade.

A marca registrada da obra é a forma complexa como os heróis são apresentados. Além de traumas e limitações, existe bastante violência explícita.

A trama em si começa quando um dos heróis (que trabalha sobre a supervisão do governo) é assassinado. Rorschach (um dos heróis que atuam clandestinamente) desconfia de um complô para matar os heróis e começa a investigar e a contactar os seus antigos companheiros. A partir daí ocorrem uma sucessão de ataques a heróis, culminando com a descoberta de um plano que coloca em risco o mundo todo.

A conclusão da história é bastante surpreendente (embora eu ache um pouco ingênua).

Outros Aspectos

Existem várias sub-histórias correndo em paralelo com a história principal. Algumas são apenas pequenos lampejos das vidas de pessoas comuns. Existe, entretanto, um história dentro da história: um dos personagens está lendo uma aventura de pirata+horror (Tales of the Black Freighter). Pessoalmente não gosto deste tipo de aventura e achei que não acrescenta nada à trama.

No final de cada revista existe um "material de apoio", simulando um jornal, revista ou outro documento do mundo real. Alguns deles tem informações relevantes para a trama mas outros são apenas complementos para aumentar a atmosfera de realidade.

Veredito

No geral eu gostei mas não achei maravilhoso. É claro que é difícil considerar como deve ter sido na época do lançamento, já que influenciou muita coisa que veio depois mas eu li antes.

Eu aconselharia outra pessoa a ler? Depende. Não é uma leitura para qualquer um. É preciso gostar de quadrinhos, estar preparado para um pouco de violência e ter a mente aberta para algo diferente das histórias convencionais.